fabric-samples/off_chain_data/application-go/store.go
Stanislav Jakuschevskij 6a5e5ddc12
Add off-chain-data go client application (#1269)
Signed-off-by: Stanislav Jakuschevskij <stas@two-giants.com>
2025-03-05 17:26:33 +00:00

80 lines
1.7 KiB
Go

package main
import (
"encoding/json"
"errors"
"fmt"
"os"
)
var errExpected = errors.New("expected error: simulated write failure")
type offChainStore struct {
path string
simulatedFailureCount, transactionCount uint
}
func newOffChainStore(path string, simulatedFailureCount uint) *offChainStore {
return &offChainStore{
path,
uint(simulatedFailureCount),
0,
}
}
// Apply writes for a given transaction to off-chain data store, ideally in a single operation for fault tolerance.
// This implementation just writes to a file.
func (ocs *offChainStore) write(data ledgerUpdate) error {
if err := ocs.simulateFailureIfRequired(); err != nil {
return err
}
writes, err := ocs.marshal(data.Writes)
if err != nil {
return err
}
return ocs.persist(writes)
}
func (ocs *offChainStore) simulateFailureIfRequired() error {
if ocs.simulatedFailureCount > 0 && ocs.transactionCount >= ocs.simulatedFailureCount {
ocs.transactionCount = 0
return errExpected
}
ocs.transactionCount += 1
return nil
}
func (ocs *offChainStore) marshal(writes []write) (string, error) {
var marshaledWrites string
for _, write := range writes {
marshaled, err := json.Marshal(write)
if err != nil {
return "", err
}
marshaledWrites += string(marshaled) + "\n"
}
return marshaledWrites, nil
}
func (ocs *offChainStore) persist(marshaledWrites string) error {
f, err := os.OpenFile(ocs.path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
if _, writeErr := f.Write([]byte(marshaledWrites)); writeErr != nil {
if closeErr := f.Close(); closeErr != nil {
return fmt.Errorf("write error: %v, close error: %v", writeErr, closeErr)
}
return writeErr
}
return f.Close()
}