Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions config/light-testnet.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# bee-light-testnet: 20 full nodes on an isolated testnet (swarm1), used for A/B runs.
# The bootnode has no ingress and is not part of the cluster definition.
clusters:
bee-light-testnet:
_inherit: ""
name: bee
namespace: bee-light-testnet
disable-namespace: true
api-domain: lightnet.testnet.internal
api-domain-internal: bee-light-testnet.svc.swarm1.local:1633
api-insecure-tls: true
api-scheme: http
funding:
eth: 0.1
gbzz: 2.0
bzz: 5.0
node-groups:
bee-1:
mode: node
bee-config: light-testnet
config: ng-light-testnet
count: 5
bee-2:
mode: node
bee-config: light-testnet
config: ng-light-testnet
count: 5
bee-3:
mode: node
bee-config: light-testnet
config: ng-light-testnet
count: 5
bee-4:
mode: node
bee-config: light-testnet
config: ng-light-testnet
count: 5

node-groups:
ng-light-testnet:
_inherit: ""

bee-configs:
light-testnet:
_inherit: ""
full-node: true

checks:
lt-pushsync-placement:
options:
chunks-per-node: 2 # per neighborhood, per uploader
mode: placement
postage-ttl: 24h
postage-depth: 22
postage-label: test-label
retry-delay: 5s
storage-radius: 2 # the radius the nodes report in /status
upload-nodes: [bee-1-2, bee-2-0, bee-3-0, bee-3-1, bee-4-3, bee-4-4]
upload-timeout: 60s
timeout: 60m
type: pushsync
lt-pushsync-placement-deferred:
options:
chunks-per-node: 2
deferred: true
mode: placement
postage-ttl: 24h
postage-depth: 22
postage-label: test-label
retry-delay: 30s # the pusher queue is busy with the background load
storage-radius: 2
upload-nodes: [bee-1-2, bee-2-0, bee-3-0, bee-3-1, bee-4-3, bee-4-4]
upload-timeout: 60s
timeout: 60m
type: pushsync
33 changes: 32 additions & 1 deletion config/local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ clusters:
bee:
bee-config: bee-local-dns
config: local-dns
count: 3
count: 5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as the minimum-storage-radius comment below: this bumps the node count of the local-dns cluster Bee's CI uses (more resources and time on every Bee PR, and it changes what ci-full-connectivity/ci-settlements etc. run against). Please keep it at 3 here and set the count on the dedicated placement cluster instead.

mode: node
light:
bee-config: bee-local-light
Expand Down Expand Up @@ -207,10 +207,14 @@ bee-configs:
bootnode-local:
_inherit: "bee-local"
bootnode-mode: true
# a forced storage radius splits the small cluster into neighborhoods, some
# of them empty, so that out-of-depth storing and shallow receipts can occur
bee-local-dns:
_inherit: "bee-local"
minimum-storage-radius: 3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocker: this changes the cluster that all of Bee's CI runs on.

Bee's .github/workflows/beekeeper.yml deploys local-dns from beekeeper master's config/local.yaml and runs ci-pushsync-chunks, ci-retrieval, ci-manifest, ci-redundancy, ci-feed, ci-soc, ci-pss, etc. against it. bee-local-autotls, bootnode-local-dns-autotls and bee-local-ultralight-autotls also _inherit: "bee-local-dns", so local-dns-autotls (beekeeper-autotls.yml) gets this too.

At radius 3 there are 8 neighborhoods; 5 random full nodes leave at least 3 of them empty (~4 on average), so roughly half of all random chunks go to an empty neighborhood:

  • Bee v2.8.2: the closest node stores them outside its AOR ("want self"), and the shallow receipt is swallowed after retries. CI still passes, just slower.
  • After bee#5390: the forwarder returns ErrOutOfDepthStoring and the origin doesn't store it either. Direct uploads fail with ErrCouldNotSync, and deferred chunks are reported CouldNotSync and never sync. About half the chunks in every other CI check would fail.

Suggestion: leave bee-local-dns (and the bee count) untouched, and add a dedicated cluster (e.g. local-dns-placement) with its own bee-config (bee-local-placement with minimum-storage-radius: 3) for the placement checks.

(Side note: the radius on bootnode-local-dns below has no effect, because Bee doesn't store pushed chunks on a node in bootnode mode: FullNodeMode && !BootnodeMode in node.go.)

bootnode-local-dns:
_inherit: "bee-local"
minimum-storage-radius: 3
bootnode-mode: true
bee-local-light:
_inherit: "bee-local"
Expand Down Expand Up @@ -304,6 +308,33 @@ checks:
- bootnode
timeout: 5m
type: pushsync
ci-pushsync-placement:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocker: on current Bee (v2.8.2), this check fails by design.

On v2.8.2, an upload to an empty neighborhood is stored outside any AOR ("want self" or a swallowed shallow receipt) and still reports success, so the check classifies it as false_success and fails. It can only pass against ethersphere/bee#5390, where those uploads fail (ErrCouldNotSync / CouldNotSync) and land in reported_failure. The metrics in placementBeeMetrics (bee_pushsync_out_of_depth_storing, bee_pusher_total_could_not_sync) also only exist in #5390 and silently read 0 otherwise.

The PR description is empty, so this dependency isn't documented anywhere. Please:

  • state the dependency on bee#5390 in the PR description, and
  • don't wire ci-pushsync-placement / ci-pushsync-placement-deferred into Bee's CI until #5390 is released.

options:
chunks-per-node: 2 # per neighborhood, per uploader
mode: placement
postage-ttl: 24h
postage-depth: 21
postage-label: test-label
retry-delay: 3s
storage-radius: 3 # must match minimum-storage-radius of the full nodes
upload-node-count: 2
upload-timeout: 30s
timeout: 30m
type: pushsync
ci-pushsync-placement-deferred:
options:
chunks-per-node: 2 # per neighborhood, per uploader
deferred: true
mode: placement
postage-ttl: 24h
postage-depth: 21
postage-label: test-label
retry-delay: 3s
storage-radius: 3 # must match minimum-storage-radius of the full nodes
upload-node-count: 2
upload-timeout: 30s
timeout: 30m
type: pushsync
ci-pushsync-light-chunks:
options:
chunks-per-node: 3
Expand Down
4 changes: 4 additions & 0 deletions pkg/bee/api/chunks.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"io"
"net/http"
"strconv"

"github.com/ethersphere/bee/v2/pkg/swarm"
)
Expand Down Expand Up @@ -36,6 +37,9 @@ func (c *ChunksService) Upload(ctx context.Context, data []byte, o UploadOptions
if o.Direct {
h.Add(deferredUploadHeader, "false")
}
if o.Tag != 0 {
h.Add(swarmTagHeader, strconv.FormatUint(o.Tag, 10))
}
h.Add(postageStampBatchHeader, o.BatchID)
err := c.client.requestWithHeader(ctx, http.MethodPost, "/"+apiVersion+"/chunks", h, bytes.NewReader(data), &resp)
return resp, err
Expand Down
31 changes: 31 additions & 0 deletions pkg/bee/api/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"context"
"fmt"
"io"
"net/http"
"time"

Expand Down Expand Up @@ -95,6 +96,36 @@ func (n *NodeService) HasChunk(ctx context.Context, a swarm.Address) (bool, erro
return true, nil
}

// HasChunkLocal reports whether the chunk is in the node's local store. Unlike
// HasChunk it uses HEAD, which never retrieves the chunk from the network and
// so does not change what the node stores.
func (n *NodeService) HasChunkLocal(ctx context.Context, a swarm.Address) (bool, error) {
err := n.client.request(ctx, http.MethodHead, "/chunks/"+a.String(), nil, nil)
if IsHTTPStatusErrorCode(err, http.StatusNotFound) {
return false, nil
} else if err != nil {
return false, err
}

return true, nil
}

// Metrics returns the node's metrics in the Prometheus text format.
func (n *NodeService) Metrics(ctx context.Context) (string, error) {
r, err := n.client.requestData(ctx, http.MethodGet, "/metrics", nil, nil)
if err != nil {
return "", err
}
defer r.Close()

b, err := io.ReadAll(r)
if err != nil {
return "", err
}

return string(b), nil
}

// Health represents node's health
type Health struct {
Status string `json:"status"`
Expand Down
11 changes: 11 additions & 0 deletions pkg/bee/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,17 @@ func (c *Client) HasChunk(ctx context.Context, a swarm.Address) (bool, error) {
return c.api.Node.HasChunk(ctx, a)
}

// HasChunkLocal reports whether the node has the chunk in its local store,
// without retrieving it from the network.
func (c *Client) HasChunkLocal(ctx context.Context, a swarm.Address) (bool, error) {
return c.api.Node.HasChunkLocal(ctx, a)
}

// Metrics returns the node's metrics in the Prometheus text format.
func (c *Client) Metrics(ctx context.Context) (string, error) {
return c.api.Node.Metrics(ctx)
}

func (c *Client) HasChunks(ctx context.Context, a []swarm.Address) (has []bool, count int, err error) {
has = make([]bool, len(a))
for i, addr := range a {
Expand Down
Loading
Loading