@cryptotaxi247 / kubo / commits / b35555978

feat: Better self-service commands for DHT providing (#10677)

* Add lastRun, NextRun, move reprovide cmd to routing. * acceleratedDHT logic * changelog * depend on latest boxo --------- Co-authored-by: guillaumemichel <guillaume@michel.id> Co-authored-by: Guillaume Michel <guillaumemichel@users.noreply.github.com>

Sergey Gorbunov committed Jan 31, 2025 at 18:33 UTC b35555978d670f81f2996f63a7a92362d65cb6df
15 files changed +80 -53
core/commands/bitswap.go
+3 -30
@@ -21,10 +21,9 @@ var BitswapCmd = &cmds.Command{
21 },
22
23 Subcommands: map[string]*cmds.Command{
24 - "stat": bitswapStatCmd,
25 - "wantlist": showWantlistCmd,
26 - "ledger": ledgerCmd,
27 - "reprovide": reprovideCmd,
24 + "stat": bitswapStatCmd,
25 + "wantlist": showWantlistCmd,
26 + "ledger": ledgerCmd,
27 },
28 }
29
@@ -200,29 +199,3 @@ prints the ledger associated with a given peer.
199 }),
200 },
201 }
203 -
204 -var reprovideCmd = &cmds.Command{
205 - Helptext: cmds.HelpText{
206 - Tagline: "Trigger reprovider.",
207 - ShortDescription: `
208 -Trigger reprovider to announce our data to network.
209 -`,
210 - },
211 - Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
212 - nd, err := cmdenv.GetNode(env)
213 - if err != nil {
214 - return err
215 - }
216 -
217 - if !nd.IsOnline {
218 - return ErrNotOnline
219 - }
220 -
221 - err = nd.Provider.Reprovide(req.Context)
222 - if err != nil {
223 - return err
224 - }
225 -
226 - return nil
227 - },
228 -}
core/commands/commands_test.go
+1 -1
@@ -20,7 +20,6 @@ func TestCommands(t *testing.T) {
20 "/add",
21 "/bitswap",
22 "/bitswap/ledger",
23 - "/bitswap/reprovide",
23 "/bitswap/stat",
24 "/bitswap/wantlist",
25 "/block",
@@ -72,6 +71,7 @@ func TestCommands(t *testing.T) {
71 "/routing/findpeer",
72 "/routing/findprovs",
73 "/routing/provide",
74 + "/routing/reprovide",
75 "/diag",
76 "/diag/cmds",
77 "/diag/cmds/clear",
core/commands/routing.go
+28
@@ -42,6 +42,7 @@ var RoutingCmd = &cmds.Command{
42 "get": getValueRoutingCmd,
43 "put": putValueRoutingCmd,
44 "provide": provideRefRoutingCmd,
45 + "reprovide": reprovideRoutingCmd,
46 },
47 }
48
@@ -235,6 +236,33 @@ var provideRefRoutingCmd = &cmds.Command{
236 Type: routing.QueryEvent{},
237 }
238
239 +var reprovideRoutingCmd = &cmds.Command{
240 + Status: cmds.Experimental,
241 + Helptext: cmds.HelpText{
242 + Tagline: "Trigger reprovider.",
243 + ShortDescription: `
244 +Trigger reprovider to announce our data to network.
245 +`,
246 + },
247 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
248 + nd, err := cmdenv.GetNode(env)
249 + if err != nil {
250 + return err
251 + }
252 +
253 + if !nd.IsOnline {
254 + return ErrNotOnline
255 + }
256 +
257 + err = nd.Provider.Reprovide(req.Context)
258 + if err != nil {
259 + return err
260 + }
261 +
262 + return nil
263 + },
264 +}
265 +
266 func provideKeys(ctx context.Context, r routing.Routing, cids []cid.Cid) error {
267 for _, c := range cids {
268 err := r.Provide(ctx, c, true)
core/commands/stat_provide.go
+20 -4
@@ -10,9 +10,15 @@ import (
10 "github.com/ipfs/boxo/provider"
11 cmds "github.com/ipfs/go-ipfs-cmds"
12 "github.com/ipfs/kubo/core/commands/cmdenv"
13 + "github.com/libp2p/go-libp2p-kad-dht/fullrt"
14 "golang.org/x/exp/constraints"
15 )
16
17 +type reprovideStats struct {
18 + provider.ReproviderStats
19 + fullRT bool
20 +}
21 +
22 var statProvideCmd = &cmds.Command{
23 Helptext: cmds.HelpText{
24 Tagline: "Returns statistics about the node's (re)provider system.",
@@ -38,32 +44,42 @@ This interface is not stable and may change from release to release.
44 if err != nil {
45 return err
46 }
47 + _, fullRT := nd.DHTClient.(*fullrt.FullRT)
48
42 - if err := res.Emit(stats); err != nil {
49 + if err := res.Emit(reprovideStats{stats, fullRT}); err != nil {
50 return err
51 }
52
53 return nil
54 },
55 Encoders: cmds.EncoderMap{
49 - cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s *provider.ReproviderStats) error {
56 + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s reprovideStats) error {
57 wtr := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
58 defer wtr.Flush()
59
60 fmt.Fprintf(wtr, "TotalProvides:\t%s\n", humanNumber(s.TotalProvides))
61 fmt.Fprintf(wtr, "AvgProvideDuration:\t%s\n", humanDuration(s.AvgProvideDuration))
62 fmt.Fprintf(wtr, "LastReprovideDuration:\t%s\n", humanDuration(s.LastReprovideDuration))
56 - fmt.Fprintf(wtr, "LastReprovideBatchSize:\t%s\n", humanNumber(s.LastReprovideBatchSize))
63 + if !s.LastRun.IsZero() {
64 + fmt.Fprintf(wtr, "LastRun:\t%s\n", humanTime(s.LastRun))
65 + if s.fullRT {
66 + fmt.Fprintf(wtr, "NextRun:\t%s\n", humanTime(s.LastRun.Add(s.ReprovideInterval)))
67 + }
68 + }
69 return nil
70 }),
71 },
60 - Type: provider.ReproviderStats{},
72 + Type: reprovideStats{},
73 }
74
75 func humanDuration(val time.Duration) string {
76 return val.Truncate(time.Microsecond).String()
77 }
78
79 +func humanTime(val time.Time) string {
80 + return val.Format("2006-01-02 15:04:05")
81 +}
82 +
83 func humanNumber[T constraints.Float | constraints.Integer](n T) string {
84 nf := float64(n)
85 str := humanSI(nf, 0)
docs/changelogs/v0.34.md
+10
@@ -6,6 +6,8 @@
6
7 - [Overview](#overview)
8 - [🔦 Highlights](#-highlights)
9 + - [Reprovide command moved to routing](#reprovide-command-moved-to-routing)
10 + - [Additional stats for Accelerated DHT Reprovides](#additional-stats-for-accelerated-dht-reprovides)
11 - [📝 Changelog](#-changelog)
12 - [👨‍👩‍👧‍👦 Contributors](#-contributors)
13
@@ -13,6 +15,14 @@
15
16 ### 🔦 Highlights
17
18 +#### Reprovide command moved to routing
19 +
20 +Moved the `bitswap reprovide` command to `routing reprovide`. ([#10677](https://github.com/ipfs/kubo/pull/10677))
21 +
22 +#### Additional stats for Accelerated DHT Reprovides
23 +
24 +The `stats reprovide` command now shows additional stats for the DHT Accelerated Client, indicating the last and next `reprovide` times. ([#10677](https://github.com/ipfs/kubo/pull/10677))
25 +
26 ### 📝 Changelog
27
28 ### 👨‍👩‍👧‍👦 Contributors
docs/examples/kubo-as-a-library/go.mod
+1 -1
@@ -7,7 +7,7 @@ go 1.23
7 replace github.com/ipfs/kubo => ./../../..
8
9 require (
10 - github.com/ipfs/boxo v0.27.2
10 + github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b
11 github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12 github.com/libp2p/go-libp2p v0.38.2
13 github.com/multiformats/go-multiaddr v0.14.0
docs/examples/kubo-as-a-library/go.sum
+2 -2
@@ -304,8 +304,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
304 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
305 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
306 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
307 -github.com/ipfs/boxo v0.27.2 h1:sGo4KdwBaMjdBjH08lqPJyt27Z4CO6sugne3ryX513s=
308 -github.com/ipfs/boxo v0.27.2/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
307 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b h1:aHVcNBIAW/eKjnFpwABp+CgbhnYGBnEDdPLN1yYHQX0=
308 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
309 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
310 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
311 github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
go.mod
+1 -1
@@ -22,7 +22,7 @@ require (
22 github.com/hashicorp/go-version v1.7.0
23 github.com/ipfs-shipyard/nopfs v0.0.14
24 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0
25 - github.com/ipfs/boxo v0.27.2
25 + github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b
26 github.com/ipfs/go-block-format v0.2.0
27 github.com/ipfs/go-cid v0.4.1
28 github.com/ipfs/go-cidutil v0.1.0
go.sum
+2 -2
@@ -368,8 +368,8 @@ github.com/ipfs-shipyard/nopfs/ipfs v0.25.0 h1:OqNqsGZPX8zh3eFMO8Lf8EHRRnSGBMqcd
368 github.com/ipfs-shipyard/nopfs/ipfs v0.25.0/go.mod h1:BxhUdtBgOXg1B+gAPEplkg/GpyTZY+kCMSfsJvvydqU=
369 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
370 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
371 -github.com/ipfs/boxo v0.27.2 h1:sGo4KdwBaMjdBjH08lqPJyt27Z4CO6sugne3ryX513s=
372 -github.com/ipfs/boxo v0.27.2/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
371 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b h1:aHVcNBIAW/eKjnFpwABp+CgbhnYGBnEDdPLN1yYHQX0=
372 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
373 github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
374 github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
375 github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
test/cli/delegated_routing_v1_http_proxy_test.go
+1 -1
@@ -72,7 +72,7 @@ func TestRoutingV1Proxy(t *testing.T) {
72
73 cidStr := nodes[0].IPFSAddStr(testutils.RandomStr(1000))
74 // Reprovide as initialProviderDelay still ongoing
75 - res := nodes[0].IPFS("bitswap", "reprovide")
75 + res := nodes[0].IPFS("routing", "reprovide")
76 require.NoError(t, res.Err)
77 res = nodes[1].IPFS("routing", "findprovs", cidStr)
78 assert.Equal(t, nodes[0].PeerID().String(), res.Stdout.Trimmed())
test/cli/delegated_routing_v1_http_server_test.go
+1 -1
@@ -40,7 +40,7 @@ func TestRoutingV1Server(t *testing.T) {
40 cidStr := nodes[2].IPFSAddStr(text)
41 _ = nodes[3].IPFSAddStr(text)
42 // Reprovide as initialProviderDelay still ongoing
43 - res := nodes[3].IPFS("bitswap", "reprovide")
43 + res := nodes[3].IPFS("routing", "reprovide")
44 require.NoError(t, res.Err)
45
46 cid, err := cid.Decode(cidStr)
test/cli/provider_test.go
+6 -6
@@ -43,7 +43,7 @@ func TestProvider(t *testing.T) {
43
44 cid := nodes[0].IPFSAddStr(time.Now().String())
45 // Reprovide as initialProviderDelay still ongoing
46 - res := nodes[0].IPFS("bitswap", "reprovide")
46 + res := nodes[0].IPFS("routing", "reprovide")
47 require.NoError(t, res.Err)
48 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
49 })
@@ -72,7 +72,7 @@ func TestProvider(t *testing.T) {
72
73 expectNoProviders(t, cid, nodes[1:]...)
74
75 - nodes[0].IPFS("bitswap", "reprovide")
75 + nodes[0].IPFS("routing", "reprovide")
76
77 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
78 })
@@ -89,7 +89,7 @@ func TestProvider(t *testing.T) {
89
90 expectNoProviders(t, cid, nodes[1:]...)
91
92 - nodes[0].IPFS("bitswap", "reprovide")
92 + nodes[0].IPFS("routing", "reprovide")
93
94 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
95 })
@@ -113,7 +113,7 @@ func TestProvider(t *testing.T) {
113 expectNoProviders(t, cidBar, nodes[1:]...)
114 expectNoProviders(t, cidBarDir, nodes[1:]...)
115
116 - nodes[0].IPFS("bitswap", "reprovide")
116 + nodes[0].IPFS("routing", "reprovide")
117
118 expectNoProviders(t, cidFoo, nodes[1:]...)
119 expectProviders(t, cidBar, nodes[0].PeerID().String(), nodes[1:]...)
@@ -141,7 +141,7 @@ func TestProvider(t *testing.T) {
141 expectNoProviders(t, cidBar, nodes[1:]...)
142 expectNoProviders(t, cidBarDir, nodes[1:]...)
143
144 - nodes[0].IPFS("bitswap", "reprovide")
144 + nodes[0].IPFS("routing", "reprovide")
145
146 expectNoProviders(t, cidFoo, nodes[1:]...)
147 expectNoProviders(t, cidBar, nodes[1:]...)
@@ -161,7 +161,7 @@ func TestProvider(t *testing.T) {
161
162 expectNoProviders(t, cid, nodes[1:]...)
163
164 - nodes[0].IPFS("bitswap", "reprovide")
164 + nodes[0].IPFS("routing", "reprovide")
165
166 expectProviders(t, cid, nodes[0].PeerID().String(), nodes[1:]...)
167 })
test/cli/routing_dht_test.go
+1 -1
@@ -85,7 +85,7 @@ func testRoutingDHT(t *testing.T, enablePubsub bool) {
85 t.Parallel()
86 hash := nodes[3].IPFSAddStr("some stuff")
87 // Reprovide as initialProviderDelay still ongoing
88 - res := nodes[3].IPFS("bitswap", "reprovide")
88 + res := nodes[3].IPFS("routing", "reprovide")
89 require.NoError(t, res.Err)
90 res = nodes[4].IPFS("routing", "findprovs", hash)
91 assert.Equal(t, nodes[3].PeerID().String(), res.Stdout.Trimmed())
test/dependencies/go.mod
+1 -1
@@ -120,7 +120,7 @@ require (
120 github.com/huin/goupnp v1.3.0 // indirect
121 github.com/inconshreveable/mousetrap v1.1.0 // indirect
122 github.com/ipfs/bbloom v0.0.4 // indirect
123 - github.com/ipfs/boxo v0.27.2 // indirect
123 + github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b // indirect
124 github.com/ipfs/go-block-format v0.2.0 // indirect
125 github.com/ipfs/go-cid v0.4.1 // indirect
126 github.com/ipfs/go-datastore v0.6.0 // indirect
test/dependencies/go.sum
+2 -2
@@ -324,8 +324,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
324 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
325 github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
326 github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
327 -github.com/ipfs/boxo v0.27.2 h1:sGo4KdwBaMjdBjH08lqPJyt27Z4CO6sugne3ryX513s=
328 -github.com/ipfs/boxo v0.27.2/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
327 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b h1:aHVcNBIAW/eKjnFpwABp+CgbhnYGBnEDdPLN1yYHQX0=
328 +github.com/ipfs/boxo v0.27.3-0.20250131141414-5c158ecc3b0b/go.mod h1:qEIRrGNr0bitDedTCzyzBHxzNWqYmyuHgK8LG9Q83EM=
329 github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
330 github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
331 github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=