Skip to content

Commit 776c21a

Browse files
fix: provider merge conflicts (#10989)
Co-authored-by: Marcin Rataj <lidel@lidel.org>
1 parent a688b7e commit 776c21a

3 files changed

Lines changed: 206 additions & 139 deletions

File tree

config/provide.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const (
1919
DefaultProvideDHTDedicatedPeriodicWorkers = 2
2020
DefaultProvideDHTDedicatedBurstWorkers = 1
2121
DefaultProvideDHTMaxProvideConnsPerWorker = 16
22-
DefaultProvideDHTKeyStoreBatchSize = 1 << 14 // ~544 KiB per batch (1 multihash = 34 bytes)
22+
DefaultProvideDHTKeystoreBatchSize = 1 << 14 // ~544 KiB per batch (1 multihash = 34 bytes)
2323
DefaultProvideDHTOfflineDelay = 2 * time.Hour
2424
)
2525

@@ -79,9 +79,9 @@ type ProvideDHT struct {
7979
// Default: DefaultProvideDHTMaxProvideConnsPerWorker
8080
MaxProvideConnsPerWorker *OptionalInteger `json:",omitempty"`
8181

82-
// KeyStoreBatchSize sets the batch size for keystore operations during reprovide refresh (sweep mode only).
83-
// Default: DefaultProvideDHTKeyStoreBatchSize
84-
KeyStoreBatchSize *OptionalInteger `json:",omitempty"`
82+
// KeystoreBatchSize sets the batch size for keystore operations during reprovide refresh (sweep mode only).
83+
// Default: DefaultProvideDHTKeystoreBatchSize
84+
KeystoreBatchSize *OptionalInteger `json:",omitempty"`
8585

8686
// OfflineDelay sets the delay after which the provider switches from Disconnected to Offline state (sweep mode only).
8787
// Default: DefaultProvideDHTOfflineDelay
@@ -150,11 +150,11 @@ func ValidateProvideConfig(cfg *Provide) error {
150150
}
151151
}
152152

153-
// Validate KeyStoreBatchSize
154-
if !cfg.DHT.KeyStoreBatchSize.IsDefault() {
155-
batchSize := cfg.DHT.KeyStoreBatchSize.WithDefault(DefaultProvideDHTKeyStoreBatchSize)
153+
// Validate KeystoreBatchSize
154+
if !cfg.DHT.KeystoreBatchSize.IsDefault() {
155+
batchSize := cfg.DHT.KeystoreBatchSize.WithDefault(DefaultProvideDHTKeystoreBatchSize)
156156
if batchSize <= 0 {
157-
return fmt.Errorf("Provide.DHT.KeyStoreBatchSize must be positive, got %d", batchSize)
157+
return fmt.Errorf("Provide.DHT.KeystoreBatchSize must be positive, got %d", batchSize)
158158
}
159159
}
160160

core/node/provider.go

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/libp2p/go-libp2p-kad-dht/fullrt"
2525
dht_pb "github.com/libp2p/go-libp2p-kad-dht/pb"
2626
dhtprovider "github.com/libp2p/go-libp2p-kad-dht/provider"
27+
"github.com/libp2p/go-libp2p-kad-dht/provider/buffered"
2728
ddhtprovider "github.com/libp2p/go-libp2p-kad-dht/provider/dual"
2829
"github.com/libp2p/go-libp2p-kad-dht/provider/keystore"
2930
routinghelpers "github.com/libp2p/go-libp2p-routing-helpers"
@@ -84,7 +85,7 @@ type DHTProvider interface {
8485
// The keys are not deleted from the keystore, so they will continue to be
8586
// reprovided as scheduled.
8687
Clear() int
87-
// RefreshSchedule scans the KeyStore for any keys that are not currently
88+
// RefreshSchedule scans the Keystore for any keys that are not currently
8889
// scheduled for reproviding. If such keys are found, it schedules their
8990
// associated keyspace region to be reprovided.
9091
//
@@ -314,13 +315,40 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
314315
}
315316
sweepingReprovider := fx.Provide(func(in providerInput) (DHTProvider, *keystore.ResettableKeystore, error) {
316317
ds := in.Repo.Datastore()
317-
keyStore, err := keystore.NewResettableKeystore(ds,
318+
ks, err := keystore.NewResettableKeystore(ds,
318319
keystore.WithPrefixBits(16),
319320
keystore.WithDatastorePath("/provider/keystore"),
320-
keystore.WithBatchSize(int(cfg.Provide.DHT.KeyStoreBatchSize.WithDefault(config.DefaultProvideDHTKeyStoreBatchSize))),
321+
keystore.WithBatchSize(int(cfg.Provide.DHT.KeystoreBatchSize.WithDefault(config.DefaultProvideDHTKeystoreBatchSize))),
321322
)
322323
if err != nil {
323-
return &NoopProvider{}, nil, err
324+
return nil, nil, err
325+
}
326+
// Constants for buffered provider configuration
327+
// These values match the upstream defaults from go-libp2p-kad-dht and have been battle-tested
328+
const (
329+
// bufferedDsName is the datastore namespace used by the buffered provider.
330+
// The dsqueue persists operations here to handle large data additions without
331+
// being memory-bound, allowing operations on hardware with limited RAM and
332+
// enabling core operations to return instantly while processing happens async.
333+
bufferedDsName = "bprov"
334+
335+
// bufferedBatchSize controls how many operations are dequeued and processed
336+
// together from the datastore queue. The worker processes up to this many
337+
// operations at once, grouping them by type for efficiency.
338+
bufferedBatchSize = 1 << 10 // 1024 items
339+
340+
// bufferedIdleWriteTime is an implementation detail of go-dsqueue that controls
341+
// how long the datastore buffer waits for new multihashes to arrive before
342+
// flushing in-memory items to the datastore. This does NOT affect providing speed -
343+
// provides happen as fast as possible via a dedicated worker that continuously
344+
// processes the queue regardless of this timing.
345+
bufferedIdleWriteTime = time.Minute
346+
)
347+
348+
bufferedProviderOpts := []buffered.Option{
349+
buffered.WithBatchSize(bufferedBatchSize),
350+
buffered.WithDsName(bufferedDsName),
351+
buffered.WithIdleWriteTime(bufferedIdleWriteTime),
324352
}
325353
var impl dhtImpl
326354
switch inDht := in.DHT.(type) {
@@ -331,7 +359,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
331359
case *dual.DHT:
332360
if inDht != nil {
333361
prov, err := ddhtprovider.New(inDht,
334-
ddhtprovider.WithKeystore(keyStore),
362+
ddhtprovider.WithKeystore(ks),
335363

336364
ddhtprovider.WithReprovideInterval(reprovideInterval),
337365
ddhtprovider.WithMaxReprovideDelay(time.Hour),
@@ -346,8 +374,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
346374
if err != nil {
347375
return nil, nil, err
348376
}
349-
_ = prov
350-
return prov, keyStore, nil
377+
return buffered.New(prov, ds, bufferedProviderOpts...), ks, nil
351378
}
352379
case *fullrt.FullRT:
353380
if inDht != nil {
@@ -365,7 +392,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
365392
selfAddrsFunc = func() []ma.Multiaddr { return impl.Host().Addrs() }
366393
}
367394
opts := []dhtprovider.Option{
368-
dhtprovider.WithKeystore(keyStore),
395+
dhtprovider.WithKeystore(ks),
369396
dhtprovider.WithPeerID(impl.Host().ID()),
370397
dhtprovider.WithRouter(impl),
371398
dhtprovider.WithMessageSender(impl.MessageSender()),
@@ -387,16 +414,19 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
387414
}
388415

389416
prov, err := dhtprovider.New(opts...)
390-
return prov, keyStore, err
417+
if err != nil {
418+
return nil, nil, err
419+
}
420+
return buffered.New(prov, ds, bufferedProviderOpts...), ks, nil
391421
})
392422

393423
type keystoreInput struct {
394424
fx.In
395425
Provider DHTProvider
396-
KeyStore *keystore.ResettableKeystore
426+
Keystore *keystore.ResettableKeystore
397427
KeyProvider provider.KeyChanFunc
398428
}
399-
initKeyStore := fx.Invoke(func(lc fx.Lifecycle, in keystoreInput) {
429+
initKeystore := fx.Invoke(func(lc fx.Lifecycle, in keystoreInput) {
400430
// Skip keystore initialization for NoopProvider
401431
if _, ok := in.Provider.(*NoopProvider); ok {
402432
return
@@ -407,12 +437,12 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
407437
done = make(chan struct{})
408438
)
409439

410-
syncKeyStore := func(ctx context.Context) error {
440+
syncKeystore := func(ctx context.Context) error {
411441
kcf, err := in.KeyProvider(ctx)
412442
if err != nil {
413443
return err
414444
}
415-
if err := in.KeyStore.ResetCids(ctx, kcf); err != nil {
445+
if err := in.Keystore.ResetCids(ctx, kcf); err != nil {
416446
return err
417447
}
418448
if err := in.Provider.RefreshSchedule(); err != nil {
@@ -424,7 +454,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
424454
lc.Append(fx.Hook{
425455
OnStart: func(ctx context.Context) error {
426456
// Set the KeyProvider as a garbage collection function for the
427-
// keystore. Periodically purge the KeyStore from all its keys and
457+
// keystore. Periodically purge the Keystore from all its keys and
428458
// replace them with the keys that needs to be reprovided, coming from
429459
// the KeyChanFunc. So far, this is the less worse way to remove CIDs
430460
// that shouldn't be reprovided from the provider's state.
@@ -434,7 +464,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
434464
// which can take a while.
435465
strategy := cfg.Provide.Strategy.WithDefault(config.DefaultProvideStrategy)
436466
logger.Infow("provider keystore sync started", "strategy", strategy)
437-
if err := syncKeyStore(ctx); err != nil {
467+
if err := syncKeystore(ctx); err != nil {
438468
logger.Errorw("provider keystore sync failed", "err", err, "strategy", strategy)
439469
} else {
440470
logger.Infow("provider keystore sync completed", "strategy", strategy)
@@ -454,7 +484,7 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
454484
case <-gcCtx.Done():
455485
return
456486
case <-ticker.C:
457-
if err := syncKeyStore(gcCtx); err != nil {
487+
if err := syncKeystore(gcCtx); err != nil {
458488
logger.Errorw("provider keystore sync", "err", err)
459489
}
460490
}
@@ -471,18 +501,16 @@ func SweepingProviderOpt(cfg *config.Config) fx.Option {
471501
case <-ctx.Done():
472502
return ctx.Err()
473503
}
474-
475504
// Keystore data isn't purged, on close, but it will be overwritten
476505
// when the node starts again.
477-
478-
return in.KeyStore.Close()
506+
return in.Keystore.Close()
479507
},
480508
})
481509
})
482510

483511
return fx.Options(
484512
sweepingReprovider,
485-
initKeyStore,
513+
initKeystore,
486514
)
487515
}
488516

0 commit comments

Comments
 (0)