gc-sender
This is the service that send bloomfilter to each storagenode.
Strictly speaking, this isn’t belongs to ranged-loop, but what does bloomfilter generation ever do without sending?
EDIT: if you already run core service, you don’t need to run this service separatedly.
Minimum useful command
./satellite-modular gc-sender \
--identity-dir=id/satellite \
--database-options.url="postgres://my_role:123456@127.0.0.1:26257/my_database?sslmode=verify-full&sslrootcert=ca.crt" \
--metainfo.database-url="postgres://my_role:123456@127.0.0.1:26257/my_metainfo_database?sslmode=verify-full&sslrootcert=ca.crt" \
--garbage-collection.bucket "my-bucket" \
--garbage-collection.access-grant "1MPU..." \
--server.extensions.revocation=false \
--server.use-peer-ca-whitelist=false
Note that this service will run non-stop in a loop, it is safe to stop it at anytime (process will resume when another gc-sender start). NO two gc-sender should be running concurrently, the current code don’t support that, bloomfilter might get send multiple times.
In production environment, some error you might encourter:
2026-08-17T04:07:33Z INFO debug:wrapper.debug debug server is started listening {"addr": "127.0.0.1:36525"}
2026-08-17T04:07:33Z INFO tracing:tracing Anonymized tracing enabled
2026-08-17T04:07:38Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:28967: connect: connection refused", "errorVerbose": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:28967: connect: connection refused\n\tstorj.io/common/rpc.HybridConnector.DialContext.func1:190"}
2026-08-17T04:08:39Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:28968: i/o timeout", "errorVerbose": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:28968: i/o timeout\n\tstorj.io/common/rpc.HybridConnector.DialContext.func1:190"}
2026-08-17T04:08:40Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: retain called with untrusted ID", "errorVerbose": "gc: retain called with untrusted ID\n\tstorj.io/storj/satellite/gc/sender.(*Service).sendRetainRequest:194\n\tstorj.io/storj/satellite/gc/sender.(*Service).RunOnce.func3.1.1:140\n\tstorj.io/common/sync2.(*Limiter).Go.func1:49"}
2026-08-17T04:09:39Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:30033: i/o timeout", "errorVerbose": "gc: rpc: tcp connector failed: rpc: dial tcp <ip_address>:30033: i/o timeout\n\tstorj.io/common/rpc.HybridConnector.DialContext.func1:190"}
2026-08-17T04:09:39Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: retain called with untrusted ID", "errorVerbose": "gc: retain called with untrusted ID\n\tstorj.io/storj/satellite/gc/sender.(*Service).sendRetainRequest:194\n\tstorj.io/storj/satellite/gc/sender.(*Service).RunOnce.func3.1.1:140\n\tstorj.io/common/sync2.(*Limiter).Go.func1:49"}
2026-08-17T04:09:42Z WARN sender:service Error sending retain filter {"node_id": "<node_id>", "error": "gc: retain called with untrusted ID", "errorVerbose": "gc: retain called with untrusted ID\n\tstorj.io/storj/satellite/gc/sender.(*Service).sendRetainRequest:194\n\tstorj.io/storj/satellite/gc/sender.(*Service).RunOnce.func3.1.1:140\n\tstorj.io/common/sync2.(*Limiter).Go.func1:49"}
I think those error are safe, it mostly error from node side.
When gc-sender finish, the directory name will change to sent-2026-08-17T04:02:34.586949988Z (it now have prefix sent).