refactor: remove FundManager.Wait
This commit is contained in:
parent
a51a62cb42
commit
0e0ffc9c10
@ -52,10 +52,6 @@ type FundManager struct {
|
||||
fundedAddrs map[address.Address]*fundedAddress
|
||||
}
|
||||
|
||||
type WaitSentinel cid.Cid
|
||||
|
||||
var WaitSentinelUndef = WaitSentinel(cid.Undef)
|
||||
|
||||
func NewFundManager(api fundManagerAPI, ds datastore.Batching) *FundManager {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
return &FundManager{
|
||||
@ -103,7 +99,9 @@ func (fm *FundManager) getFundedAddress(addr address.Address) *fundedAddress {
|
||||
|
||||
// Reserve adds amt to `reserved`. If there are not enough available funds for
|
||||
// the address, submits a message on chain to top up available funds.
|
||||
func (fm *FundManager) Reserve(ctx context.Context, wallet, addr address.Address, amt abi.TokenAmount) (WaitSentinel, error) {
|
||||
// Returns the cid of the message that was submitted on chain, or cid.Undef if
|
||||
// the required funds were already available.
|
||||
func (fm *FundManager) Reserve(ctx context.Context, wallet, addr address.Address, amt abi.TokenAmount) (cid.Cid, error) {
|
||||
return fm.getFundedAddress(addr).reserve(ctx, wallet, amt)
|
||||
}
|
||||
|
||||
@ -114,16 +112,11 @@ func (fm *FundManager) Release(addr address.Address, amt abi.TokenAmount) error
|
||||
|
||||
// Withdraw unreserved funds. Only succeeds if there are enough unreserved
|
||||
// funds for the address.
|
||||
func (fm *FundManager) Withdraw(ctx context.Context, wallet, addr address.Address, amt abi.TokenAmount) (WaitSentinel, error) {
|
||||
// Returns the cid of the message that was submitted on chain.
|
||||
func (fm *FundManager) Withdraw(ctx context.Context, wallet, addr address.Address, amt abi.TokenAmount) (cid.Cid, error) {
|
||||
return fm.getFundedAddress(addr).withdraw(ctx, wallet, amt)
|
||||
}
|
||||
|
||||
// Waits for a reserve or withdraw to complete.
|
||||
func (fm *FundManager) Wait(ctx context.Context, sentinel WaitSentinel) error {
|
||||
_, err := fm.api.StateWaitMsg(ctx, cid.Cid(sentinel), build.MessageConfidence)
|
||||
return err
|
||||
}
|
||||
|
||||
// FundedAddressState keeps track of the state of an address with funds in the
|
||||
// datastore
|
||||
type FundedAddressState struct {
|
||||
@ -178,7 +171,7 @@ func (a *fundedAddress) start() {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *fundedAddress) reserve(ctx context.Context, wallet address.Address, amt abi.TokenAmount) (WaitSentinel, error) {
|
||||
func (a *fundedAddress) reserve(ctx context.Context, wallet address.Address, amt abi.TokenAmount) (cid.Cid, error) {
|
||||
return a.requestAndWait(ctx, wallet, amt, &a.reservations)
|
||||
}
|
||||
|
||||
@ -187,11 +180,11 @@ func (a *fundedAddress) release(amt abi.TokenAmount) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *fundedAddress) withdraw(ctx context.Context, wallet address.Address, amt abi.TokenAmount) (WaitSentinel, error) {
|
||||
func (a *fundedAddress) withdraw(ctx context.Context, wallet address.Address, amt abi.TokenAmount) (cid.Cid, error) {
|
||||
return a.requestAndWait(ctx, wallet, amt, &a.withdrawals)
|
||||
}
|
||||
|
||||
func (a *fundedAddress) requestAndWait(ctx context.Context, wallet address.Address, amt abi.TokenAmount, reqs *[]*fundRequest) (WaitSentinel, error) {
|
||||
func (a *fundedAddress) requestAndWait(ctx context.Context, wallet address.Address, amt abi.TokenAmount, reqs *[]*fundRequest) (cid.Cid, error) {
|
||||
// Create a request and add it to the request queue
|
||||
req := newFundRequest(ctx, wallet, amt)
|
||||
|
||||
@ -205,9 +198,9 @@ func (a *fundedAddress) requestAndWait(ctx context.Context, wallet address.Addre
|
||||
// Wait for the results
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return WaitSentinelUndef, ctx.Err()
|
||||
return cid.Undef, ctx.Err()
|
||||
case r := <-req.Result:
|
||||
return WaitSentinel(r.msgCid), r.err
|
||||
return r.msgCid, r.err
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,9 +41,7 @@ func TestFundManagerBasic(t *testing.T) {
|
||||
msg := s.mockApi.getSentMessage(sentinel)
|
||||
checkAddMessageFields(t, msg, s.walletAddr, s.acctAddr, amt)
|
||||
|
||||
s.mockApi.completeMsg(cid.Cid(sentinel))
|
||||
err = s.fm.Wait(s.ctx, sentinel)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinel)
|
||||
|
||||
// Reserve 7
|
||||
// balance: 10 -> 17
|
||||
@ -55,9 +53,7 @@ func TestFundManagerBasic(t *testing.T) {
|
||||
msg = s.mockApi.getSentMessage(sentinel)
|
||||
checkAddMessageFields(t, msg, s.walletAddr, s.acctAddr, amt)
|
||||
|
||||
s.mockApi.completeMsg(cid.Cid(sentinel))
|
||||
err = s.fm.Wait(s.ctx, sentinel)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinel)
|
||||
|
||||
// Release 5
|
||||
// balance: 17
|
||||
@ -76,9 +72,7 @@ func TestFundManagerBasic(t *testing.T) {
|
||||
msg = s.mockApi.getSentMessage(sentinel)
|
||||
checkWithdrawMessageFields(t, msg, s.walletAddr, s.acctAddr, amt)
|
||||
|
||||
s.mockApi.completeMsg(cid.Cid(sentinel))
|
||||
err = s.fm.Wait(s.ctx, sentinel)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinel)
|
||||
|
||||
// Reserve 3
|
||||
// balance: 15
|
||||
@ -90,7 +84,7 @@ func TestFundManagerBasic(t *testing.T) {
|
||||
sentinel, err = s.fm.Reserve(s.ctx, s.walletAddr, s.acctAddr, amt)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, msgCount, s.mockApi.messageCount())
|
||||
require.Equal(t, sentinel, WaitSentinelUndef)
|
||||
require.Equal(t, sentinel, cid.Undef)
|
||||
|
||||
// Reserve 1
|
||||
// balance: 15 -> 16
|
||||
@ -102,7 +96,7 @@ func TestFundManagerBasic(t *testing.T) {
|
||||
sentinel, err = s.fm.Reserve(s.ctx, s.walletAddr, s.acctAddr, amt)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.mockApi.completeMsg(cid.Cid(sentinel))
|
||||
s.mockApi.completeMsg(sentinel)
|
||||
msg = s.mockApi.getSentMessage(sentinel)
|
||||
checkAddMessageFields(t, msg, s.walletAddr, s.acctAddr, topUp)
|
||||
|
||||
@ -145,7 +139,7 @@ func TestFundManagerParallel(t *testing.T) {
|
||||
withdrawReady <- err
|
||||
}()
|
||||
|
||||
reserveSentinels := make(chan WaitSentinel)
|
||||
reserveSentinels := make(chan cid.Cid)
|
||||
|
||||
// Reserve 3
|
||||
go func() {
|
||||
@ -174,7 +168,7 @@ func TestFundManagerParallel(t *testing.T) {
|
||||
<-queueReady
|
||||
|
||||
// Complete the "Reserve 10" message
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelReserve10))
|
||||
s.mockApi.completeMsg(sentinelReserve10)
|
||||
msg := s.mockApi.getSentMessage(sentinelReserve10)
|
||||
checkAddMessageFields(t, msg, s.walletAddr, s.acctAddr, abi.NewTokenAmount(10))
|
||||
|
||||
@ -193,7 +187,7 @@ func TestFundManagerParallel(t *testing.T) {
|
||||
}
|
||||
|
||||
// Complete the message
|
||||
s.mockApi.completeMsg(cid.Cid(rs1))
|
||||
s.mockApi.completeMsg(rs1)
|
||||
msg = s.mockApi.getSentMessage(rs1)
|
||||
|
||||
// "Reserve 3" +3
|
||||
@ -233,7 +227,7 @@ func TestFundManagerReserveByWallet(t *testing.T) {
|
||||
})
|
||||
|
||||
type reserveResult struct {
|
||||
ws WaitSentinel
|
||||
ws cid.Cid
|
||||
err error
|
||||
}
|
||||
results := make(chan *reserveResult)
|
||||
@ -282,9 +276,7 @@ func TestFundManagerReserveByWallet(t *testing.T) {
|
||||
checkAddMessageFields(t, msg, walletAddrA, s.acctAddr, amtA1)
|
||||
|
||||
// Complete wallet A message
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelA1))
|
||||
err = s.fm.Wait(s.ctx, sentinelA1)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinelA1)
|
||||
|
||||
resB1 := <-results
|
||||
resB2 := <-results
|
||||
@ -313,7 +305,7 @@ func TestFundManagerWithdrawalLimit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Complete the "Reserve 10" message
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelReserve10))
|
||||
s.mockApi.completeMsg(sentinelReserve10)
|
||||
|
||||
// Release 10
|
||||
err = s.fm.Release(s.acctAddr, amt)
|
||||
@ -338,7 +330,7 @@ func TestFundManagerWithdrawalLimit(t *testing.T) {
|
||||
|
||||
type withdrawResult struct {
|
||||
reqIndex int
|
||||
ws WaitSentinel
|
||||
ws cid.Cid
|
||||
err error
|
||||
}
|
||||
withdrawRes := make(chan *withdrawResult)
|
||||
@ -379,10 +371,6 @@ func TestFundManagerWithdrawalLimit(t *testing.T) {
|
||||
// Expect withdrawal requests that fit under reserved amount to be combined
|
||||
// into a single message on-chain
|
||||
require.Equal(t, results[0].ws, results[1].ws)
|
||||
|
||||
s.mockApi.completeMsg(cid.Cid(results[0].ws))
|
||||
err = s.fm.Wait(s.ctx, results[0].ws)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestFundManagerWithdrawByWallet verifies that withdraw requests are grouped by wallet
|
||||
@ -399,7 +387,7 @@ func TestFundManagerWithdrawByWallet(t *testing.T) {
|
||||
reserveAmt := abi.NewTokenAmount(10)
|
||||
sentinelReserve, err := s.fm.Reserve(s.ctx, s.walletAddr, s.acctAddr, reserveAmt)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelReserve))
|
||||
s.mockApi.completeMsg(sentinelReserve)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
@ -408,7 +396,7 @@ func TestFundManagerWithdrawByWallet(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
type withdrawResult struct {
|
||||
ws WaitSentinel
|
||||
ws cid.Cid
|
||||
err error
|
||||
}
|
||||
results := make(chan *withdrawResult)
|
||||
@ -476,9 +464,7 @@ func TestFundManagerWithdrawByWallet(t *testing.T) {
|
||||
checkWithdrawMessageFields(t, msg, walletAddrA, s.acctAddr, amtA1)
|
||||
|
||||
// Complete wallet A message
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelA1))
|
||||
err = s.fm.Wait(s.ctx, sentinelA1)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinelA1)
|
||||
|
||||
resB1 := <-results
|
||||
resB2 := <-results
|
||||
@ -520,9 +506,7 @@ func TestFundManagerRestart(t *testing.T) {
|
||||
checkAddMessageFields(t, msg2, s.walletAddr, acctAddr2, amt2)
|
||||
|
||||
// Complete "Address 1: Reserve 10"
|
||||
s.mockApi.completeMsg(cid.Cid(sentinelAddr1))
|
||||
err = s.fm.Wait(s.ctx, sentinelAddr1)
|
||||
require.NoError(t, err)
|
||||
s.mockApi.completeMsg(sentinelAddr1)
|
||||
|
||||
// Give the completed state a moment to be stored before restart
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
@ -534,7 +518,7 @@ func TestFundManagerRestart(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
amt3 := abi.NewTokenAmount(9)
|
||||
reserveSentinel := make(chan WaitSentinel)
|
||||
reserveSentinel := make(chan cid.Cid)
|
||||
go func() {
|
||||
// Address 2: Reserve 9
|
||||
sentinel3, err := fmAfter.Reserve(s.ctx, s.walletAddr, acctAddr2, amt3)
|
||||
@ -551,9 +535,7 @@ func TestFundManagerRestart(t *testing.T) {
|
||||
}
|
||||
|
||||
// Complete "Address 2: Reserve 7"
|
||||
mockApiAfter.completeMsg(cid.Cid(sentinelAddr2Res7))
|
||||
err = fmAfter.Wait(s.ctx, sentinelAddr2Res7)
|
||||
require.NoError(t, err)
|
||||
mockApiAfter.completeMsg(sentinelAddr2Res7)
|
||||
|
||||
// Expect waiting message to now be sent
|
||||
sentinel3 := <-reserveSentinel
|
||||
@ -574,12 +556,12 @@ type scaffold struct {
|
||||
func setup(t *testing.T) *scaffold {
|
||||
ctx := context.Background()
|
||||
|
||||
wallet, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
wllt, err := wallet.NewWallet(wallet.NewMemKeyStore())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
walletAddr, err := wallet.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
walletAddr, err := wllt.WalletNew(context.Background(), types.KTSecp256k1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -587,12 +569,12 @@ func setup(t *testing.T) *scaffold {
|
||||
acctAddr := tutils.NewActorAddr(t, "addr")
|
||||
|
||||
mockApi := newMockFundManagerAPI(walletAddr)
|
||||
ds := ds_sync.MutexWrap(ds.NewMapDatastore())
|
||||
fm := NewFundManager(mockApi, ds)
|
||||
dstore := ds_sync.MutexWrap(ds.NewMapDatastore())
|
||||
fm := NewFundManager(mockApi, dstore)
|
||||
return &scaffold{
|
||||
ctx: ctx,
|
||||
ds: ds,
|
||||
wllt: wallet,
|
||||
ds: dstore,
|
||||
wllt: wllt,
|
||||
walletAddr: walletAddr,
|
||||
acctAddr: acctAddr,
|
||||
mockApi: mockApi,
|
||||
@ -658,11 +640,10 @@ func (mapi *mockFundManagerAPI) MpoolPushMessage(ctx context.Context, message *t
|
||||
return smsg, nil
|
||||
}
|
||||
|
||||
func (mapi *mockFundManagerAPI) getSentMessage(ws WaitSentinel) *types.Message {
|
||||
func (mapi *mockFundManagerAPI) getSentMessage(c cid.Cid) *types.Message {
|
||||
mapi.lk.Lock()
|
||||
defer mapi.lk.Unlock()
|
||||
|
||||
c := cid.Cid(ws)
|
||||
for i := 0; i < 1000; i++ {
|
||||
if pending, ok := mapi.sentMsgs[c]; ok {
|
||||
return &pending.msg.Message
|
||||
|
Loading…
Reference in New Issue
Block a user