85 lines
3.0 KiB
Go
85 lines
3.0 KiB
Go
|
package storageadapter
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/filecoin-project/go-state-types/abi"
|
||
|
actorsmarket "github.com/filecoin-project/lotus/chain/actors/builtin/market"
|
||
|
"github.com/filecoin-project/lotus/chain/events"
|
||
|
"github.com/filecoin-project/lotus/chain/events/state"
|
||
|
"github.com/filecoin-project/lotus/chain/types"
|
||
|
)
|
||
|
|
||
|
// dealStateMatcher caches the DealStates for the most recent
|
||
|
// old/new tipset combination
|
||
|
type dealStateMatcher struct {
|
||
|
preds *state.StatePredicates
|
||
|
|
||
|
lk sync.Mutex
|
||
|
oldTsk types.TipSetKey
|
||
|
newTsk types.TipSetKey
|
||
|
oldDealStateRoot actorsmarket.DealStates
|
||
|
newDealStateRoot actorsmarket.DealStates
|
||
|
}
|
||
|
|
||
|
func newDealStateMatcher(preds *state.StatePredicates) *dealStateMatcher {
|
||
|
return &dealStateMatcher{preds: preds}
|
||
|
}
|
||
|
|
||
|
// matcher returns a function that checks if the state of the given dealID
|
||
|
// has changed.
|
||
|
// It caches the DealStates for the most recent old/new tipset combination.
|
||
|
func (mc *dealStateMatcher) matcher(ctx context.Context, dealID abi.DealID) events.StateMatchFunc {
|
||
|
// The function that is called to check if the deal state has changed for
|
||
|
// the target deal ID
|
||
|
dealStateChangedForID := mc.preds.DealStateChangedForIDs([]abi.DealID{dealID})
|
||
|
|
||
|
// The match function is called by the events API to check if there's
|
||
|
// been a state change for the deal with the target deal ID
|
||
|
match := func(oldTs, newTs *types.TipSet) (bool, events.StateChange, error) {
|
||
|
mc.lk.Lock()
|
||
|
defer mc.lk.Unlock()
|
||
|
|
||
|
// Check if we've already fetched the DealStates for the given tipsets
|
||
|
if mc.oldTsk == oldTs.Key() && mc.newTsk == newTs.Key() {
|
||
|
// If we fetch the DealStates and there is no difference between
|
||
|
// them, they are stored as nil. So we can just bail out.
|
||
|
if mc.oldDealStateRoot == nil || mc.newDealStateRoot == nil {
|
||
|
return false, nil, nil
|
||
|
}
|
||
|
|
||
|
// Check if the deal state has changed for the target ID
|
||
|
return dealStateChangedForID(ctx, mc.oldDealStateRoot, mc.newDealStateRoot)
|
||
|
}
|
||
|
|
||
|
// We haven't already fetched the DealStates for the given tipsets, so
|
||
|
// do so now
|
||
|
|
||
|
// Replace dealStateChangedForID with a function that records the
|
||
|
// DealStates so that we can cache them
|
||
|
var oldDealStateRootSaved, newDealStateRootSaved actorsmarket.DealStates
|
||
|
recorder := func(ctx context.Context, oldDealStateRoot, newDealStateRoot actorsmarket.DealStates) (changed bool, user state.UserData, err error) {
|
||
|
// Record DealStates
|
||
|
oldDealStateRootSaved = oldDealStateRoot
|
||
|
newDealStateRootSaved = newDealStateRoot
|
||
|
|
||
|
return dealStateChangedForID(ctx, oldDealStateRoot, newDealStateRoot)
|
||
|
}
|
||
|
|
||
|
// Call the match function
|
||
|
dealDiff := mc.preds.OnStorageMarketActorChanged(
|
||
|
mc.preds.OnDealStateChanged(recorder))
|
||
|
matched, data, err := dealDiff(ctx, oldTs.Key(), newTs.Key())
|
||
|
|
||
|
// Save the recorded DealStates for the tipsets
|
||
|
mc.oldTsk = oldTs.Key()
|
||
|
mc.newTsk = newTs.Key()
|
||
|
mc.oldDealStateRoot = oldDealStateRootSaved
|
||
|
mc.newDealStateRoot = newDealStateRootSaved
|
||
|
|
||
|
return matched, data, err
|
||
|
}
|
||
|
return match
|
||
|
}
|