Skip to content

Commit e2a129e

Browse files
icellanmrz1836
andauthored
Add DHT mode and cleanup interval configuration (#8)
* Added option to set DHT to client mode only and configure the cleanup interval * test(dht): standardize struct field alignment in configuration tests * Refactor DHT configuration tests to eliminate code duplication - Extract common test setup into createTestClient helper function - Consolidate overlapping tests (TestDHTModeDefault, TestDHTModeServer, TestDHTModeClient) into TestDHTModeSelection - Merge TestDHTModeServerWithVariousCleanupIntervals into TestDHTCleanupIntervalConfiguration - Reduce test count from 11 to 5 while maintaining full coverage - Use t.Helper() and t.Cleanup() for better test organization - Add descriptive assertion messages for clearer failures - Improve benchmark error handling Changes: - Lines of code reduced: 416 -> 312 (25% reduction) - Tests consolidated: 11 -> 5 (same coverage, better organization) - Code duplication eliminated: 9 repeated log setups, 11 repeated client creations now use 1 helper - All tests still pass with identical coverage * refactor(tests): improve client closure handling in DHT tests * refactor(types): clarify P2PClient alias for backward compatibility * refactor(tests): handle client closure errors in DHT tests * refactor(tests): replace hardcoded log messages with constants * chore(deps): update dependabot configuration for Go modules Added Go modules configuration for the /example/ directory to ensure weekly updates for direct dependencies, including security patterns and commit message prefixing. * chore(deps): update module versions in go.mod and go.sum Updated dependencies to their latest versions for improved stability and performance. * chore(deps): update indirect dependencies in go.mod and go.sum --------- Co-authored-by: Mr. Z <mrz1836@users.noreply.github.com>
1 parent d7ceda3 commit e2a129e

File tree

9 files changed

+474
-62
lines changed

9 files changed

+474
-62
lines changed

.github/dependabot.yml

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,36 @@ updates:
5656
include: "scope"
5757

5858
# ──────────────────────────────────────────────────────────────
59-
# 2. GitHub Actions Workflows
59+
# 2. Go Modules (go.mod / go.sum)
60+
# ──────────────────────────────────────────────────────────────
61+
- package-ecosystem: "gomod"
62+
directory: "/example/"
63+
target-branch: "master"
64+
schedule:
65+
interval: "weekly"
66+
day: "monday"
67+
time: "09:00"
68+
timezone: "America/New_York"
69+
allow:
70+
- dependency-type: "direct"
71+
groups:
72+
security-deps:
73+
patterns:
74+
- "*crypto*"
75+
- "*security*"
76+
- "*auth*"
77+
- "*jwt*"
78+
- "*oauth*"
79+
update-types: ["minor", "patch"]
80+
open-pull-requests-limit: 10
81+
assignees: ["mrz1836"]
82+
labels: ["chore", "dependencies", "gomod"]
83+
commit-message:
84+
prefix: "chore"
85+
include: "scope"
86+
87+
# ──────────────────────────────────────────────────────────────
88+
# 3. GitHub Actions Workflows
6089
# ──────────────────────────────────────────────────────────────
6190
- package-ecosystem: "github-actions"
6291
directory: "/"
@@ -79,7 +108,7 @@ updates:
79108
include: "scope"
80109

81110
# ──────────────────────────────────────────────────────────────
82-
# 3. DevContainer (devcontainer.json : base image + features)
111+
# 4. DevContainer (devcontainer.json : base image + features)
83112
# ──────────────────────────────────────────────────────────────
84113
- package-ecosystem: "devcontainers"
85114
directory: "/"

client.go

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"github.com/libp2p/go-libp2p"
2121
dht "github.com/libp2p/go-libp2p-kad-dht"
22+
"github.com/libp2p/go-libp2p-kad-dht/records"
2223
pubsub "github.com/libp2p/go-libp2p-pubsub"
2324
"github.com/libp2p/go-libp2p/core/crypto"
2425
"github.com/libp2p/go-libp2p/core/host"
@@ -27,6 +28,9 @@ import (
2728
"github.com/libp2p/go-libp2p/p2p/discovery/mdns"
2829
drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
2930
"github.com/multiformats/go-multiaddr"
31+
32+
ds "github.com/ipfs/go-datastore"
33+
dssync "github.com/ipfs/go-datastore/sync"
3034
)
3135

3236
var (
@@ -92,7 +96,7 @@ func NewClient(config Config) (Client, error) {
9296
}
9397

9498
// Set up DHT
95-
kadDHT, err := setupDHT(ctx, h, bootstrapPeers, clientLogger, cancel)
99+
kadDHT, err := setupDHT(ctx, h, config, bootstrapPeers, clientLogger, cancel)
96100
if err != nil {
97101
return nil, err
98102
}
@@ -204,8 +208,46 @@ func createHost(_ context.Context, hostOpts []libp2p.Option, config Config, rela
204208
return h, nil
205209
}
206210

207-
func setupDHT(ctx context.Context, h host.Host, bootstrapPeers []peer.AddrInfo, _ logger, cancel context.CancelFunc) (*dht.IpfsDHT, error) {
208-
kadDHT, err := dht.New(ctx, h, dht.Mode(dht.ModeServer), dht.BootstrapPeers(bootstrapPeers...))
211+
func setupDHT(ctx context.Context, h host.Host, config Config, bootstrapPeers []peer.AddrInfo, log logger, cancel context.CancelFunc) (*dht.IpfsDHT, error) {
212+
// Determine DHT mode (default to server)
213+
mode := dht.ModeServer
214+
if config.DHTMode == "client" {
215+
mode = dht.ModeClient
216+
log.Infof("DHT mode: client (query-only, no provider storage)")
217+
} else {
218+
log.Infof("DHT mode: server (will advertise and store provider records)")
219+
}
220+
221+
// Build DHT options
222+
dhtOpts := []dht.Option{
223+
dht.Mode(mode),
224+
dht.BootstrapPeers(bootstrapPeers...),
225+
}
226+
227+
// If server mode and custom cleanup interval specified, configure ProviderManager
228+
if mode == dht.ModeServer && config.DHTCleanupInterval > 0 {
229+
log.Infof("Configuring DHT cleanup interval: %v", config.DHTCleanupInterval)
230+
231+
// Create an in-memory datastore for the provider manager
232+
// Same as default DHT datastore creation
233+
datastore := dssync.MutexWrap(ds.NewMapDatastore())
234+
235+
providerManager, err := records.NewProviderManager(
236+
ctx,
237+
h.ID(),
238+
h.Peerstore(),
239+
datastore,
240+
records.CleanupInterval(config.DHTCleanupInterval),
241+
)
242+
if err != nil {
243+
_ = h.Close()
244+
cancel()
245+
return nil, fmt.Errorf("failed to create provider manager: %w", err)
246+
}
247+
dhtOpts = append(dhtOpts, dht.ProviderStore(providerManager))
248+
}
249+
250+
kadDHT, err := dht.New(ctx, h, dhtOpts...)
209251
if err != nil {
210252
_ = h.Close()
211253
cancel()

config.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,22 @@ type Config struct {
7979
// If not provided, bootstrap peers will be used as relays.
8080
// Example: []string{"/ip4/1.2.3.4/tcp/4001/p2p/QmPeerID"}
8181
RelayPeers []string
82+
83+
// DHTMode specifies whether this node runs the DHT in client or server mode.
84+
// Valid values: "client", "server"
85+
// - "client": Can query DHT but doesn't advertise itself or store provider records.
86+
// No ProviderManager cleanup overhead.
87+
// - "server": Participates fully in DHT, advertises itself, stores provider records.
88+
// Has periodic cleanup overhead. Default mode for proper P2P networks.
89+
// If not provided or empty, defaults to "server" mode.
90+
DHTMode string
91+
92+
// DHTCleanupInterval is the interval at which the DHT's ProviderManager performs
93+
// garbage collection of expired provider records. The cleanup involves querying all
94+
// provider records and removing expired entries.
95+
// Only applies when DHTMode is "server".
96+
// If not provided or zero, uses the DHT default (1 hour).
97+
// Recommended: 6-24 hours for production to reduce CPU overhead.
98+
// The cleanup frequency trades off between memory usage (stale records) and CPU usage.
99+
DHTCleanupInterval time.Duration
82100
}

0 commit comments

Comments
 (0)