Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
146
vendor/github.com/ipld/go-ipld-prime/node/basicnode/HACKME.md
generated
vendored
Normal file
146
vendor/github.com/ipld/go-ipld-prime/node/basicnode/HACKME.md
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
hackme
|
||||
======
|
||||
|
||||
Design rationale are documented here.
|
||||
|
||||
This doc is not necessary reading for users of this package,
|
||||
but if you're considering submitting patches -- or just trying to understand
|
||||
why it was written this way, and check for reasoning that might be dated --
|
||||
then it might be useful reading.
|
||||
|
||||
### scalars are just typedefs
|
||||
|
||||
This is noteworthy because in codegen, this is typically *not* the case:
|
||||
in codegen, even scalar types are boxed in a struct, such that it prevents
|
||||
casting values into those types.
|
||||
|
||||
This casting is not a concern for the node implementations in this package, because
|
||||
|
||||
- A) we don't have any kind of validation rules to make such casting worrying; and
|
||||
- B) since our types are unexported, casting is still blocked by this anyway.
|
||||
|
||||
### about builders for scalars
|
||||
|
||||
The assembler types for scalars (string, int, etc) are pretty funny-looking.
|
||||
You might wish to make them work without any state at all!
|
||||
|
||||
The reason this doesn't fly is that we have to keep the "wip" value in hand
|
||||
just long enough to return it from the `NodeBuilder.Build` method -- the
|
||||
`NodeAssembler` contract for `Assign*` methods doesn't permit just returning
|
||||
their results immediately.
|
||||
|
||||
(Another possible reason is if we expected to use these assemblers on
|
||||
slab-style allocations (say, `[]plainString`)...
|
||||
however, this is inapplicable at present, because
|
||||
A) we don't (except places that have special-case internal paths anyway); and
|
||||
B) the types aren't exported, so users can't either.)
|
||||
|
||||
Does this mean that using `NodeBuilder` for scalars has a completely
|
||||
unnecessary second allocation, which is laughably inefficient? Yes.
|
||||
It's unfortunate the interfaces constrain us to this.
|
||||
**But**: one typically doesn't actually use builders for scalars much;
|
||||
they're just here for completeness.
|
||||
So this is less of a problem in practice than it might at first seem.
|
||||
|
||||
More often, one will use the "any" builder (which is has a whole different set
|
||||
of design constraints and tradeoffs);
|
||||
or, if one is writing code and knows which scalar they need, the exported
|
||||
direct constructor function for that kind
|
||||
(e.g., `String("foo")` instead of `Prototype__String{}.NewBuilder().AssignString("foo")`)
|
||||
will do the right thing and do it in one allocation (and it's less to type, too).
|
||||
|
||||
### maps and list keyAssembler and valueAssemblers have custom scalar handling
|
||||
|
||||
Related to the above heading.
|
||||
|
||||
Maps and lists in this package do their own internal handling of scalars,
|
||||
using unexported features inside the package, because they can more efficient.
|
||||
|
||||
### when to invalidate the 'w' pointers
|
||||
|
||||
The 'w' pointer -- short for 'wip' node pointer -- has an interesting lifecycle.
|
||||
|
||||
In a NodeAssembler, the 'w' pointer should be intialized before the assembler is used.
|
||||
This means either the matching NodeBuilder type does so; or,
|
||||
if we're inside recursive structure, the parent assembler did so.
|
||||
|
||||
The 'w' pointer is used throughout the life of the assembler.
|
||||
|
||||
Setting the 'w' pointer to nil is one of two mechanisms used internally
|
||||
to mark that assembly has become "finished" (the other mechanism is using
|
||||
an internal state enum field).
|
||||
Setting the 'w' pointer to nil has two advantages:
|
||||
one is that it makes it *impossible* to continue to mutate the target node;
|
||||
the other is that we need no *additional* memory to track this state change.
|
||||
However, we can't use the strategy of nilling 'w' in all cases: in particular,
|
||||
when in the NodeBuilder at the root of some construction,
|
||||
we need to continue to hold onto the node between when it becomes "finished"
|
||||
and when Build is called; otherwise we can't actually return the value!
|
||||
Different stratgies are therefore used in different parts of this package.
|
||||
|
||||
Maps and lists use an internal state enum, because they already have one,
|
||||
and so they might as well; there's no additional cost to this.
|
||||
Since they can use this state to guard against additional mutations after "finish",
|
||||
the map and list assemblers don't bother to nil their own 'w' at all.
|
||||
|
||||
During recursion to assemble values _inside_ maps and lists, it's interesting:
|
||||
the child assembler wrapper type takes reponsibility for nilling out
|
||||
the 'w' pointer in the child assembler's state, doing this at the same time as
|
||||
it updates the parent's state machine to clear proceeding with the next entry.
|
||||
|
||||
In the case of scalars at the root of a build, we took a shortcut:
|
||||
we actually don't fence against repeat mutations at all.
|
||||
*You can actually use the assign method more than once*.
|
||||
We can do this without breaking safety contracts because the scalars
|
||||
all have a pass-by-value phase somewhere in their lifecycle
|
||||
(calling `nb.AssignString("x")`, then `n := nb.Build()`, then `nb.AssignString("y")`
|
||||
won't error if `nb` is a freestanding builder for strings... but it also
|
||||
won't result in mutating `n` to contain `"y"`, so overall, it's safe).
|
||||
|
||||
We could normalize the case with scalars at the root of a tree so that they
|
||||
error more aggressively... but currently we haven't bothered, since this would
|
||||
require adding another piece of memory to the scalar builders; and meanwhile
|
||||
we're not in trouble on compositional correctness.
|
||||
|
||||
Note that these remarks are for the `basicnode` package, but may also
|
||||
apply to other implementations too (e.g., our codegen output follows similar
|
||||
overall logic).
|
||||
|
||||
### NodePrototypes are available through a singleton
|
||||
|
||||
Every NodePrototype available from this package is exposed as a field
|
||||
in a struct of which there's one public exported instance available,
|
||||
called 'Prototype'.
|
||||
|
||||
This means you can use it like this:
|
||||
|
||||
```go
|
||||
nbm := basicnode.Prototype.Map.NewBuilder()
|
||||
nbs := basicnode.Prototype.String.NewBuilder()
|
||||
nba := basicnode.Prototype.Any.NewBuilder()
|
||||
// etc
|
||||
```
|
||||
|
||||
(If you're interested in the performance of this: it's free!
|
||||
Methods called at the end of the chain are inlinable.
|
||||
Since all of the types of the structures on the way there are zero-member
|
||||
structs, the compiler can effectively treat them as constants,
|
||||
and thus freely elide any memory dereferences that would
|
||||
otherwise be necessary to get methods on such a value.)
|
||||
|
||||
### NodePrototypes are (also) available as exported concrete types
|
||||
|
||||
The 'Prototype' singleton is one way to access the NodePrototype in this package;
|
||||
their exported types are another equivalent way.
|
||||
|
||||
```go
|
||||
basicnode.Prototype.Map = basicnode.Prototype.Map
|
||||
```
|
||||
|
||||
It is recommended to use the singleton style;
|
||||
they compile to identical assembly, and the singleton is syntactically prettier.
|
||||
|
||||
We may make these concrete types unexported in the future.
|
||||
A decision on this is deferred until some time has passed and
|
||||
we can accumulate reasonable certainty that there's no need for an exported type
|
||||
(such as type assertions, etc).
|
||||
Reference in New Issue
Block a user