Skip to content

Consolidation step 3 of 8: the DHT package, one partition per former header [androidbuild] [iosbuild]#44

Merged
ptesavol merged 5 commits into
mainfrom
consolidate/c3-dht
Jul 4, 2026
Merged

Consolidation step 3 of 8: the DHT package, one partition per former header [androidbuild] [iosbuild]#44
ptesavol merged 5 commits into
mainfrom
consolidate/c3-dht

Conversation

@ptesavol

@ptesavol ptesavol commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

The largest consolidation step — and the pull request where the module architecture was settled through your three directives, each one measured before and after.

The settled architecture

  1. One file per former header. All forty-five DHT public headers (5,013 lines) are individual module files under modules/, in the familiar directory tree, and the header directory is deleted. Git tracks them as renames, preserving history.
  2. Named sub-modules, not partitionsstreamr.dht.Identifiers, not a partition. The language forbids importing a partition from outside the module, and you required tests to import exactly what they test: all forty-one DHT test files now import their subjects directly, so editing one sub-module no longer rebuilds unrelated tests.
  3. No umbrella module. A re-exporting umbrella was built and measured, then deleted: its compiled interface depends on every sub-module, so anyone importing it re-inherits the edit-anything-rebuild-everything amplification. Every consumer — inside the package, in trackerless-network, in the proxy client — imports the individual sub-modules it uses, exactly mirroring the old header includes.

The measurements (same two edits, whole-tree release rebuild)

Structure Mid-chain edit Leaf edit
Partitions behind a re-exporting primary ~480 s ~440 s
Named sub-modules behind an umbrella 418 s 546 s
No umbrella (this pull request) 129 s 135 s

What remains is honest cost: those modules sit at the center of the real dependency graph. Genuinely narrow edits — a test, an unimported leaf — rebuild in seconds. The CI build-directory caching planned for after the series amortizes the rest.

Trackerless-network retrofitted

The step-two package was converted to the same architecture in this pull request: partitions became named sub-modules, its umbrella is gone, and its tests plus the proxy client import narrowly. Its message-reference ordering operator moved into the exported protocol-types module — as an unexported file-scope function it was invisible to other modules instantiating the container templates.

Rules the compiler taught us, recorded in the plan for the five remaining packages

  • Each module unit must directly import what its own code uses — inherited visibility through another module's exports does not carry; the compiler names the missing module explicitly.
  • Shorthand declarations inherited textually from neighboring headers need the file's own declaration.
  • A forward declaration of another module's class inside a module attaches the name to the wrong module and conflicts with the real definition — the import replaces it.
  • The include-hygiene finds: the string header for branded-key containers in sixteen units, plus a handful of other standard and folly headers, each named by the compiler.

Also here (as instructed, no separate pull requests)

  • The CI-speed follow-up plan in MODERNIZATION.md (build-directory caching per platform, packaging check on one platform, compiler cache as complement, port randomization for parallel tests).
  • The import std verdict including the release 30 beta 1 retest: not adoptable — the blockers are in Android's C library itself, unchanged in the pre-release; a clean build-system workaround for the cross-compilation detection defect was found and recorded, so the adoption recipe for a future fixed toolkit is small and concrete.
  • Incidental fixes: the DHT standalone install script's committed address-sanitizer flags removed (fatal to downstream standalone links once real code lived in module objects); the race fix from pull request Fix the third connection-establishment race: replay PendingConnection events to late listeners #43 ported into the affected sub-module; one test file excluded from the code-analysis step under the approved selective-disabling policy (the compiler accepts it; the analysis tool cannot follow folly's customization points through module interfaces).

Verification

Full release build; DHT tests 83/83 including the two new race tests; trackerless-network 12+1; proxy client 15/15; standalone builds of the whole chain; package lints green across all module units. Android and iOS builds run via the title keywords.

🤖 Generated with Claude Code

@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Third and largest consolidation step, and the step where the module
architecture was settled through three owner directives, each measured:

1. ONE FILE PER FORMER HEADER: all 45 dht public headers (5,013 lines)
   became individual module units under modules/ in the old directory
   tree; the include/ tree is deleted.
2. NAMED SUB-MODULES, NOT PARTITIONS (streamr.dht.X): partitions
   cannot be imported by external translation units, and tests must
   import exactly the sub-modules they test ("tests are internal to
   the module"). All 41 dht test files import their subjects directly.
3. NO UMBRELLA MODULE: a re-exporting umbrella was built, measured,
   and deleted - its compiled interface depends on every sub-module,
   so anyone importing it reinherits edit-anything-rebuild-everything.
   Consumers import the individual sub-modules they use, mirroring the
   old header includes one to one.

MEASURED (same mid-chain/leaf sub-module touch, whole-tree Release
rebuild): partitions behind a re-exporting primary ~480 s; named
sub-modules behind an umbrella 418/546 s; no umbrella 129/135 s.
Remaining cost is the true dependency cone of central types plus the
serial BMI chain; narrow edits rebuild in seconds.

The already-consolidated trackerless-network package was RETROFITTED
to the same architecture in this PR (partitions -> named sub-modules,
umbrella deleted, tests + proxyclient import narrowly). Its MessageRef
ordering operator moved from FifoMapWithTTL to the exported protos
module: as a non-exported file-scope function it had module linkage
and was unreachable from other modules instantiating the templates.

Sub-module strictness rules learned (recorded in MODERNIZATION.md for
the remaining packages):
- every unit must DIRECTLY import what its code uses (the compiler
  names the missing module); shorthand names inherited textually from
  neighboring headers need the file's own using-declaration;
- a purview forward declaration of another module's class attaches the
  name to the wrong module and conflicts with the defining one - the
  import replaces it;
- include hygiene: <string> for Branded-key containers (16 units),
  <functional>, <mutex>, <exception>, folly Collect.h named explicitly
  by the compiler.

Incidental fixes: dht standalone install.sh had committed
-fsanitize=address in every configure (fatal for downstream standalone
links once real code moved into module objects) - removed; PR #43's
ReplayEventEmitter race fix ported into the IPendingConnection
sub-module (the header it patched no longer exists);
ConnectionLockingTest.cpp excluded from clangd-tidy (owner-approved
selective disabling - the analysis tool cannot resolve folly
customization points through module interfaces; the compiler accepts
the file; also gains folly Collect.h textually since it instantiates
the imported streamr::utils::collect).

Also in MODERNIZATION.md per owner instruction: the CI-speed follow-up
plan (build-directory caching, single-platform packaging check, ccache
complement, port randomization) and the import-std verdict incl. the
NDK r30 beta 1 retest (do not adopt; blockers are in Bionic itself,
unchanged in the pre-release; clean CMake cross-probe workaround found
and recorded for a future fixed NDK).

Verified: full Release build; dht tests 83/83 (incl. the two new PR
#43 race tests); trackerless-network 12+1; proxyclient 15/15;
standalone builds of the whole chain; package lints green over all
module units.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ptesavol ptesavol force-pushed the consolidate/c3-dht branch from 08cf255 to 1a1caca Compare July 4, 2026 17:05
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

The module libraries' objects end up inside the shared
libstreamrproxyclient. macOS emits position-independent code by
default, but on Linux the ELF linker rejects the standalone archives
otherwise (R_AARCH64_ADR_PREL_PG_HI21 relocations against the module
vtable/thunk symbols, "recompile with -fPIC") - first surfaced on the
linux-arm64 leg once the consolidated code moved into module objects.
Set uniformly in the StreamrModules.cmake helpers (canonical + synced
copies).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

The implementation file imports many module interfaces; analysing
several such files concurrently exhausted memory on the 2-core CI
runners (clangd dies mid-protocol, clangd-tidy reports "Invalid header
end"). The package has a handful of files - serial analysis costs
seconds and preserves full coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Even serial analysis of src/streamrproxyclient.cpp exhausts memory on
the 2-core 7 GB CI runners: the file imports module interfaces from
four packages and clangd builds that whole module graph in one
process. Owner-approved selective disabling; the compiler builds the
file on every platform and clang-format still checks it. Revisit when
runners grow or clangd's module memory use shrinks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

…64 runner

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 4, 2026

Copy link
Copy Markdown

Bugbot is not enabled for this team, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@ptesavol ptesavol merged commit 3cacf86 into main Jul 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant