mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 23:45:10 +00:00
80 lines
1.7 KiB
Go
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()
|
|
}
|