diff --git a/storagemarket/impl/provider.go b/storagemarket/impl/provider.go index 9c5635ec..e09f5b8f 100644 --- a/storagemarket/impl/provider.go +++ b/storagemarket/impl/provider.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "sort" "time" "github.com/hannahhoward/go-pubsub" @@ -454,6 +455,14 @@ func (p *Provider) RetryDealPublishing(propcid cid.Cid) error { return p.deals.Send(propcid, storagemarket.ProviderEventRestart) } +func (p *Provider) LocalDealCount() (int, error) { + var out []storagemarket.MinerDeal + if err := p.deals.List(&out); err != nil { + return 0, err + } + return len(out), nil +} + // ListLocalDeals lists deals processed by this storage provider func (p *Provider) ListLocalDeals() ([]storagemarket.MinerDeal, error) { var out []storagemarket.MinerDeal @@ -469,6 +478,38 @@ func (p *Provider) GetLocalDeal(propCid cid.Cid) (storagemarket.MinerDeal, error return d, err } +func (p *Provider) ListLocalDealsPage(offsetPropCid *cid.Cid, count int) ([]storagemarket.MinerDeal, error) { + if count == 0 { + return []storagemarket.MinerDeal{}, nil + } + + // Get all deals + var deals []storagemarket.MinerDeal + if err := p.deals.List(&deals); err != nil { + return nil, err + } + + // Sort by creation time descending + sort.Slice(deals, func(i, j int) bool { + return deals[i].CreationTime.Time().After(deals[j].CreationTime.Time()) + }) + + // Iterate through deals until we reach the target signed proposal cid, + // then add deals from that point up to count + page := make([]storagemarket.MinerDeal, 0, count) + for _, dl := range deals { + if offsetPropCid == nil || dl.ProposalCid == *offsetPropCid { + page = append(page, dl) + offsetPropCid = nil // add all deals from this point on + } + if len(page) == count { + return page, nil + } + } + + return page, nil +} + // SetAsk configures the storage miner's ask with the provided price, // duration, and options. Any previously-existing ask is replaced. func (p *Provider) SetAsk(price abi.TokenAmount, verifiedPrice abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error { diff --git a/storagemarket/impl/provider_test.go b/storagemarket/impl/provider_test.go index 09556a0b..8162bb3f 100644 --- a/storagemarket/impl/provider_test.go +++ b/storagemarket/impl/provider_test.go @@ -168,6 +168,47 @@ func TestProvider_Migrations(t *testing.T) { } require.Equal(t, expectedDeal, deal) } + + // Verify get deal by signed proposal cid + deal, err := provider.GetLocalDeal(deals[0].ProposalCid) + require.NoError(t, err) + require.Equal(t, deals[0].ProposalCid, deal.ProposalCid) + + // Verify the deal count + count, err := provider.LocalDealCount() + require.NoError(t, err) + require.Equal(t, len(deals), count) + + // Verify get a page of deals without a nil offset proposal cid + listedDeals, err := provider.ListLocalDealsPage(nil, len(deals)) + require.NoError(t, err) + require.Len(t, listedDeals, len(deals)) + for i, dl := range listedDeals { + if i == 0 { + continue + } + // Verify descending order by creation time + require.True(t, dl.CreationTime.Time().Before(listedDeals[i-1].CreationTime.Time())) + } + firstDeal := listedDeals[0] + secondDeal := listedDeals[1] + thirdDeal := listedDeals[2] + + // Verify get a page of deals with a nil offset proposal cid and with a limit + listedDeals, err = provider.ListLocalDealsPage(nil, 2) + require.NoError(t, err) + require.Len(t, listedDeals, 2) + // Verify correct deals + require.Equal(t, firstDeal.ProposalCid, listedDeals[0].ProposalCid) + require.Equal(t, secondDeal.ProposalCid, listedDeals[1].ProposalCid) + + // Verify get a page of deals with an offset proposal cid and with a limit + listedDeals, err = provider.ListLocalDealsPage(&secondDeal.ProposalCid, 2) + require.NoError(t, err) + require.Len(t, listedDeals, 2) + // Verify correct deals + require.Equal(t, secondDeal.ProposalCid, listedDeals[0].ProposalCid) + require.Equal(t, thirdDeal.ProposalCid, listedDeals[1].ProposalCid) } func TestHandleDealStream(t *testing.T) { diff --git a/storagemarket/provider.go b/storagemarket/provider.go index fe5af826..88df9ca6 100644 --- a/storagemarket/provider.go +++ b/storagemarket/provider.go @@ -36,10 +36,19 @@ type StorageProvider interface { // GetAsk returns the storage miner's ask, or nil if one does not exist. GetAsk() *SignedStorageAsk + // GetLocalDeal gets a deal by signed proposal cid + GetLocalDeal(cid cid.Cid) (MinerDeal, error) + + // LocalDealCount gets the number of local deals + LocalDealCount() (int, error) + // ListLocalDeals lists deals processed by this storage provider ListLocalDeals() ([]MinerDeal, error) - GetLocalDeal(propCid cid.Cid) (MinerDeal, error) + // ListLocalDealsPage lists deals by creation time descending, starting + // at the deal with the given signed proposal cid and returning up to + // count deals + ListLocalDealsPage(offsetPropCid *cid.Cid, count int) ([]MinerDeal, error) // AddStorageCollateral adds storage collateral AddStorageCollateral(ctx context.Context, amount abi.TokenAmount) error