diff --git a/storagemarket/impl/providerstates/provider_states.go b/storagemarket/impl/providerstates/provider_states.go index f8c851305..d137510a6 100644 --- a/storagemarket/impl/providerstates/provider_states.go +++ b/storagemarket/impl/providerstates/provider_states.go @@ -4,6 +4,8 @@ import ( "context" "fmt" "io" + "strings" + "time" "github.com/ipfs/go-cid" logging "github.com/ipfs/go-log/v2" @@ -29,6 +31,11 @@ import ( var log = logging.Logger("providerstates") +var ( + RetryInterval = 2 * time.Minute + MaxAttempts = 10 +) + // TODO: These are copied from spec-actors master, use spec-actors exports when we update const DealMaxLabelSize = 256 @@ -274,20 +281,32 @@ func WaitForFunding(ctx fsm.Context, environment ProviderDealEnvironment, deal s // PublishDeal sends a message to publish a deal on chain func PublishDeal(ctx fsm.Context, environment ProviderDealEnvironment, deal storagemarket.MinerDeal) error { - smDeal := storagemarket.MinerDeal{ - Client: deal.Client, - ClientDealProposal: deal.ClientDealProposal, - ProposalCid: deal.ProposalCid, - State: deal.State, - Ref: deal.Ref, - } + attempt := 0 - mcid, err := environment.Node().PublishDeals(ctx.Context(), smDeal) - if err != nil { - return ctx.Trigger(storagemarket.ProviderEventNodeErrored, xerrors.Errorf("publishing deal: %w", err)) - } + for { + attempt++ + RetryInterval *= 2 + + smDeal := storagemarket.MinerDeal{ + Client: deal.Client, + ClientDealProposal: deal.ClientDealProposal, + ProposalCid: deal.ProposalCid, + State: deal.State, + Ref: deal.Ref, + } - return ctx.Trigger(storagemarket.ProviderEventDealPublishInitiated, mcid) + mcid, err := environment.Node().PublishDeals(ctx.Context(), smDeal) + if err != nil { + if strings.Contains(err.Error(), "not enough funds") && attempt <= MaxAttempts { + log.Warnf("publishing deal failed due to lack of funds: %s; retrying again after backoff interval: %s", err, RetryInterval) + time.Sleep(RetryInterval) + continue + } + return ctx.Trigger(storagemarket.ProviderEventNodeErrored, xerrors.Errorf("publishing deal: %w", err)) + } + + return ctx.Trigger(storagemarket.ProviderEventDealPublishInitiated, mcid) + } } // WaitForPublish waits for the publish message on chain and saves the deal id