Runnable examples are maintained in the central Nexss Ecosystem Examples repository.
Nexss Kernel is a lightweight, typed Go execution library for building reusable actions, resilient pipelines, and deterministic DAG workflows. It is independent of concrete transport protocols, persistence implementations, AI vendor SDKs, and specific identity providers.
The Kernel provides core execution semantics, typed generics, context-based security guards, and resilient middleware. Applications and sibling modules supply concrete network adapters, storage drivers, and domain logic.
Kernel does not expose a runtime Version function or constant. Go binaries built with module metadata can inspect runtime/debug.ReadBuildInfo for the linked module version.
Design goal: Predictable execution semantics, focused interfaces, zero-allocation hot paths, and idiomatic Go.
This repository uses Task for local workflows and CI. Install it once with:
go install github.com/go-task/task/v3/cmd/task@latestUse task --list to view targets. Common commands:
task test # short test suite
task test -- ./action # test one package or path
task test:race # race-enabled tests
task bench # benchmarks with memory statistics
task ci # the CI gateApplication / Domain Package / Transport Adapters
│
├── Domain builders (appaction pattern)
├── HTTP / CLI / Worker / NATS / gRPC adapters
├── AI, Tooling & Provider modules
└── Database, Cache & Storage implementations
│
▼
Nexss Kernel
typed actions · Builder · middleware · hooks · retry
cache/idempotency contracts · context guards (RBAC/perms)
composition · DAG graphs · categorized errors (xerr)
The Kernel owns the lifecycle, concurrency safety, and execution semantics of an action. Extension modules implement backend drivers or add explicit middleware layers; they do not fork the builder or alter execution semantics.
| Package | Purpose |
|---|---|
action |
Typed action builders, middleware, composition, retries, timeouts, circuit breakers, concurrency limits, caching, idempotency, durable journaling/resume, streaming, sagas, and resilience policies. |
ai/dag |
Typed directed acyclic graphs with deterministic compilation, static and conditional routing, layered parallel execution, nested graphs, state snapshots, Mermaid rendering, and suspension/resume semantics. |
stream |
Domain-neutral lazy stream operators, including Map, Filter, Take, Batch, BatchByTime, Window, Reduce, FlatMap, Distinct, Throttle, Debounce, and worker pools. |
observe |
Optional vendor-neutral lifecycle events, bounded memory history, metrics aggregation, Prometheus, JSONL, and slog sinks. |
xctx |
Typed request context values, pooled request scopes, request/execution/trace identity, correlation data, roles, permissions, features, progress, and deterministic controls. |
xerr |
Categorized errors for validation, authorization, conflicts, not-found cases, transient failures, internal failures, and panic recovery. |
xfile / xfs |
Typed file references and resolvers, plus confined and atomic filesystem helpers. |
broadcast / ringbuf |
In-process topics and bounded ring buffers for event publication and telemetry. |
timing / xsync |
Timing-wheel scheduling and generic pooling primitives. |
xtest/ktest |
Allocation checks, polling/leak helpers, test contexts, action fakes, contract assertions, and fluent action test runs. |
ringbuf.NewChecked(capacity) validates the rounded allocation against the default 64 MiB per-ring budget and returns an error before allocating. For an intentional per-ring override, use ringbuf.NewWithOptions(ringbuf.Options{Capacity: ..., MemoryBudgetBytes: ...}). The source-compatible ringbuf.New(capacity) also uses the safe default and returns nil when validation fails; over-limit requests are never silently clamped to a smaller ring.
The generic mutex-backed ringbuf.NewBuffer[T](capacity) uses the same default budget and returns nil on rejection. Use NewBufferChecked[T] to inspect an error or NewBufferWithOptions[T] to set an explicit per-buffer budget. The estimate includes the buffer header and backing array, but excludes allocator overhead and objects reachable through pointers in T. For zero-size T, no per-element bytes are counted, so the byte budget does not cap logical capacity. action.NewHistory and observe.NewMemorySink use the same budget; use action.NewHistoryChecked / action.NewHistoryWithOptions or observe.NewMemorySinkChecked / observe.NewMemorySinkWithOptions to inspect errors or select explicit budgets. Builder methods WithHistoryChecked / RecordHistoryChecked return allocation errors, while their WithOptions variants accept explicit limits. Legacy RecordHistory causes Do to return a configuration error rather than run without the requested history.
Actions are typed generic functions wrapped with fluent middleware pipelines. Request and response types are inferred from the handler signature without reflection on the hot path:
package main
import (
"context"
"fmt"
"time"
"github.com/nexssp/kernel/action"
)
type UserRequest struct {
ID string `json:"id"`
}
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
func main() {
lookupUser := action.New("user.lookup", func(ctx context.Context, req UserRequest) (User, error) {
return User{ID: req.ID, Name: "Alice"}, nil
}).
Timeout(2 * time.Second).
Retry(2, action.ExponentialBackoff(25*time.Millisecond, 2*time.Second)).
Build()
user, err := lookupUser.Do(context.Background(), UserRequest{ID: "usr-42"})
if err != nil {
panic(err)
}
fmt.Printf("User: %s (%s)\n", user.Name, user.ID)
}The Kernel supports type-erased and dynamic execution boundaries (such as AI tool-calling agents, plugin registries, and generic HTTP routers) without weakening typed internal handlers:
act := action.New("user.lookup", lookupHandler).Build()
// 1. Direct type-erased call: zero heap allocations when matching Req and Res are pointers.
// A value-type Res may allocate when it is boxed into any.
result, err := act.DoAny(ctx, UserRequest{ID: "usr-42"})
// 2. Universal Invoker: automatically decodes and coerces dynamic payloads
result, err = action.InvokeAny(ctx, act, map[string]any{"id": "usr-42"})
// 3. Coerce: converts dynamic structures (JSON, maps, strings) into target types
req, err := action.Coerce[UserRequest](untypedInput)
// 4. Dynamic lifting: lifts AnyAction into *Builder[any, any] for composition
dynamicAct := action.Dynamic(act).Build()Pipe[Req, Mid, Res]connects two actions sequentially (A → B).PipeWith[Req, Mid1, Mid2, Res]connects two actions with an inline transformation function, avoiding intermediate adapter structs.Chain[T]executes same-typed actions sequentially, piping output to input.BranchandBranchAnyroute execution conditionally using a router function.FirstSuccessruns fallback chains, returning the first non-error result.Parallelexecutes typed actions concurrently over the same request (scatter-gather).ParallelNamedandParallelMapexecute heterogeneous actions concurrently, collecting results into amap[string]any.
// Pipeline with zero-allocation inline field transform
pipeline := action.PipeWith("user.process",
fetchUserAct,
func(ctx context.Context, u User) (string, error) { return u.Email, nil },
sendEmailAct,
).Build()
// Heterogeneous concurrent execution
reviewer := action.ParallelNamed[string]("review.suite", map[string]action.AnyAction{
"security": checkSecurityAct,
"linter": runLinterAct,
}).Build()
results, err := reviewer.Do(ctx, "package main...")Retryretries only transient errors identified byxerr.IsTransient.RetryIfevaluates an application-definedRetryPredicate(err error) bool.RetryAllretries on any non-nil error (intended for idempotent batch jobs).InferredResilient/SmartResilienceconfigures an adaptive circuit breaker and exponential jitter retry driven automatically byxerr.Kind. It fast-fails 4xx errors (BadRequest,Unauthorized,Forbidden,NotFound,Validation) without consuming retries.Adaptiveapplies a circuit breaker with dynamic timeout scaling and half-open state recovery.- Standalone and adaptive breakers count caller deadline expirations as failures; explicit caller cancellation is excluded. A handler that ignores its context can keep a half-open probe occupied until it returns.
ExponentialBackoff(base, max)doubles wait duration per attempt.ExponentialJitter(base, max)adds ±30% random jitter to mitigate thundering-herd spikes.LinearBackoff(step)andConstantBackoff(duration).
Dedup(keyFn)applies singleflight deduplication. Callers sharing a key block until active execution completes, receiving copies of the result. Context cancellation of a joined caller does not cancel the flight.Coalesce(coalescer, keyFn)shares in-flight results across actions. A canceled waiter may exit without terminating the background execution for other callers.ConcurrencyLimit(limit)enforces an in-process ceiling using atomic counters. Excess calls returnErrConcurrencyLimit.RateLimit,RateLimitWithKey, andRateLimitDistributedprovide token-bucket admission control.AdaptiveLoadSheddingevaluates system statistics (CPU percentage and goroutine count) against priority tiers (PriorityCritical,PriorityNormal,PriorityLow), dropping non-essential traffic when thresholds are exceeded.
FanOut(ctx, act, reqs, maxConcurrency)executes concurrent items while preserving input order in the returned slice. A non-positive concurrency limit usesDefaultAsyncMaxConcurrency(16), and the whole call is bounded byDefaultAsyncTimeout(2 minutes) unless the parent context ends sooner; useFanOutWithOptionsto change either.Race(ctx, act, reqs)returns the first successful result and cancels losing attempts. Handlers must cooperate with context cancellation.
Cache(ttl, keyFn, layers...) coordinates L1 (local memory) through LN (distributed) stores:
- Cache hits return without invoking the underlying handler.
- Cache misses execute the handler under singleflight protection to prevent cache stampedes.
- Slower-layer hits automatically back-fill faster layers.
- If no layers are passed, an internal thread-safe in-memory cache is instantiated. It evicts entries inline during
Setand lazily duringGet; it starts no janitor goroutine and requires noClose()call. Once()memoizes the result or error of the first execution indefinitely for static configurations.
.Idempotent()and.IdempotentWithConfig(cfg)enable replay only when a caller supplies an explicit key. Transport adapters should readcfg.Header()(defaultIdempotency-Key) and bind it withxctx.WithIdempotencyKey(ctx, key).RequestIDis correlation-only; neither it nor a payload hash is used as a fallback key. For typed requests, configureRequestKeyFunc; the olderKeyFuncremains available for[]byterequests.- Builder-created actions default
Namespaceto their final action name; directIdempotencyMiddlewareuse requires an explicit namespace. Versioned v2 storage keys include the namespace and a fingerprint of tenant, user, and authorization scope, and do not store the raw client key. Because the persisted key format changed, old idempotency entries will not be replayed by this version; expire or migrate them as part of deployment. MemoryIdempotencyStoreprovides in-memory reference coordination.IdempotencyCoordinatordefines atomic claim semantics (Claim,Complete,Release) with leased in-progress locks and request hash validation to detect duplicate payload conflicts.- Reusing a key for a different payload returns
Conflict; corrupt responses or missing/corrupt saved request hashes fail closed instead of executing the handler again. Successful responses are replayed only until the configured TTL expires. Handler errors are not cached and may be retried; expired distributed claims may be taken over while the original handler is still running. Use downstream idempotency or fencing when repeating side effects is unsafe. - Same-process callers share one active execution. Shared work keeps the leader's context values but not its cancellation; coalescing and deduplication use
DefaultSharedFlightTimeout(2 minutes), while idempotency usesIdempotencyConfig.FlightTimeout(default 2 minutes). Each caller can stop waiting on its own cancellation, but the synchronous leader call may remain blocked until the handler returns or the shared timeout expires.MaxConcurrentFlightsbounds unique idempotency keys (default 256); no background handler goroutines are started. - This active-flight cap applies to
Idempotency;DedupandCoalescedo not expose aMaxConcurrentFlightslimit. High-cardinality distinct keys can therefore grow their in-flight state without a configured bound under load; account for this when choosing those middleware for untrusted or bursty traffic. - Durable and idempotent results are persisted as JSON. For empty-interface result types, including named empty interfaces, the first successful call is normalized to the same standard values returned by JSON replay (numbers are
float64, objects aremap[string]any, arrays are[]any, and typed nil pointers/maps/slices become nil). Concrete result types use normalencoding/jsondecoding into their declaredRestype on replay. A non-empty interface generally cannot be reconstructed from JSON as its original concrete dynamic type, so use a concrete result type when replay must succeed; arbitrary dynamic Go types are not restored from persisted type names. - A
Journal.RecordSteperror or idempotency completion error can be ambiguous: the write may have committed before the error was returned. Durable journals do not guarantee exactly-once external side effects after an ambiguous write failure; use downstream idempotency/fencing or a storage protocol with definitive commit outcomes when repeats are unsafe.
DigestBytesandDigestStringcreate fixed-size SHA-256 bindings without heap allocation on the comparison path.ExecutionIdentitybinds an execution to its execution namespace, source digest, input digest, and contract digest.DurableWithResumeextendsDurablewith journal-backed identity validation before replay.- A changed source or input returns an
xerr.Conflict; callers may useResumeOptions{Force: true, ForceReason: ...}to create an explicit successor generation. ResumeJournalstores identity metadata alongside the existingJournalcontract. Durable replay and singleflight remain owned by the shared Kernel runner.
Exclusive(mutex, ttl, keyFn)acquires an application-providedMutexbefore execution and releases it upon completion. Contention returnsErrLocked.LeaderOnly(mutex, ttl)runs the action under a fixed leader key.
ExclusiveFenced(fencedMutex, ttl, keyFn)andLeaderOnlyFencedacquire aLockLeasecontaining a monotonically increasing fence counter.- An internal ticker renews the lease at
ttl / 3. If lease renewal fails or the lease is lost, the action context is canceled immediately to abort in-flight work. - Handlers retrieve the lease via
action.LeaseFromContext(ctx).
Contract Notice: Fencing is only effective if the downstream database or storage operation validates the token (e.g.,
UPDATE ... WHERE fence >= @fence). The Kernel coordinates lease lifecycle and cancellation; it cannot enforce fencing on storage engines that do not verify the token.
action.NewSaga[Req, Res] coordinates distributed operations with compensating transactions:
AddStep(name, do, undo)registers forward work and its reverse compensation.AddOptionalStep(name, do, undo)registers steps that may fail without triggering a saga abort.- If a mandatory step fails or panics, registered
Undofunctions execute in reverse order (LIFO) under an uncancelled context. .AsAction()converts the compiled saga into an executable*BuiltAction[Req, SagaResult[Res]].
action.NewStream wraps Go 1.23+ iter.Seq2 handlers under action lifecycle management. NewStreamOp composes typed stream actions, while StreamWorkerPool adds bounded per-item parallelism:
stream := action.NewStream("telemetry.stream", func(ctx context.Context, req Query) (iter.Seq2[Record, error], error) {
return func(yield func(Record, error) bool) {
for i := 0; i < req.Limit; i++ {
if ctx.Err() != nil {
yield(Record{}, ctx.Err())
return
}
if !yield(Record{ID: i}, nil) {
return // Consumer stopped early
}
}
}, nil
})
seq, err := stream.Do(ctx, Query{Limit: 100})
for record, err := range seq {
// Zero heap allocation streaming
}CollectStream materializes an iterator into an in-memory slice when streaming is not required. The stream package also provides time-based grouping (BatchByTime), sliding windows, throttling, debouncing, distinct filtering, and context-aware operators. Use the supplied context; do not substitute context.Background() inside an operator.
action.NewStateMachine guards entity lifecycle transitions:
- Handlers implement
StateEntity(GetState(),SetState()). Allow(from, to...)registers permissible transitions.- Disallowed transitions are rejected with
xerr.KindConflictbefore committing state changes.
The ai/dag package compiles directed acyclic graphs into deterministic, concurrent execution layers:
graph, err := dag.New("order.workflow").
AddNode("validate", "val_out", validateAction).
AddNode("reserve", "res_out", reserveAction).
AddNode("charge", "chg_out", chargeAction).
AddEdge("validate", "reserve").
AddEdge("validate", "charge").
Compile()
if err != nil {
return err
}
initialState := dag.AcquireState()
defer initialState.Release()
finalState, err := graph.Execute(ctx, initialState)
if err != nil {
return err
}
defer finalState.Release()
res, err := dag.GetNodeOutput[ReserveResult](finalState, "reserve")- Cycle Detection: Compiles layers using Kahn's algorithm; circular dependencies return
xerr.KindConflict. - Namespaced Outputs: Node outputs are stored under
tasks.<node_id>.outputto prevent key collisions during parallel execution. - Pooled State:
Stateinstances utilizesync.Pool. Read operations during layer execution are zero-lock. Callers must callstate.Release()when finished. - Sub-graph Nesting: A compiled DAG can be converted into an action via
.AsAction()and embedded directly as a node in a parent DAG. - Mermaid Export:
graph.ToMermaid()exports deterministic, formatted Mermaid flowchart diagrams.
Workflows that require asynchronous human intervention (approvals, manual reviews, external callbacks) are supported natively via dag.ErrSuspended:
// 1. Initial execution halts at approval step
state, err := graph.Execute(ctx, initialState)
if errors.Is(err, dag.ErrSuspended) {
// Partial progress is preserved; persist state snapshot to storage
db.SaveWorkflow(workflowID, state.Data())
state.Release()
return
}
// 2. Later: Resume after human approval
savedSnapshot := db.LoadWorkflow(workflowID)
resumeState := dag.AcquireState()
for k, v := range savedSnapshot { resumeState.Set(k, v) }
defer resumeState.Release()
// Completed node actions are skipped; routing is evaluated again from entry
finalState, err := graph.Execute(ctx, resumeState)- When a node returns
dag.ErrSuspended,Executereturns(partialState, dag.ErrSuspended)without purging the state from memory. - A resumed dynamic DAG starts traversal again at its configured entry. Node actions whose output key (
tasks.<nodeID>.output) is already present inStateare skipped, but conditional-edge routers run again on each traversal. - A router must choose the same target for the same persisted state and stable graph configuration. Do not rely on time, randomness, or mutable external state when a resumed workflow must follow the same branch; a route may change intentionally when the persisted state or graph configuration changes.
xctx manages request-scoped metadata without heap allocations on standard paths:
NewScope(parent)obtains a pooled*RequestScope. Call the returnedcleanup()function upon request completion to return the scope tosync.Pool.- Context helpers provide typed accessors:
WithUserID,WithTenantID,WithRoles,WithPermissions,WithFeatures,WithTraceID. - Request-scope setters, accessors, and authorization checks synchronize mutable metadata; direct field access through
ScopeFromremains the caller's synchronization responsibility. - Each accessor acquires a scope lock. For related multi-field reads,
SnapshotFrom(ctx)takes one read lock and returns a detached identity/authorization snapshot; it clones role, permission, and feature slices (so it may allocate) and intentionally omits the separately locked trace-event ring. Use typed accessors for isolated reads; opt into a snapshot when a coherent multi-field view justifies the copy cost. CloneForAsync(ctx)clones request metadata into a detached context, preserving tracing and identity while decoupling from the parent cancellation tree.
WriteFileAtomic syncs the parent directory after rename on POSIX and returns a sync error even though the rename may already have taken effect. Windows renames remain atomic but cannot be made crash-durable with directory fsync.
RequireAuth()rejects unauthenticated contexts (xerr.KindUnauthorized).RequireTenant()requires a populated tenant ID.RequireRole(role)andRequireAnyRole(roles...)enforce RBAC claims.RequirePermission(perm)verifies granular permission strings (supports wildcard*).RequireFeature(flags...)andRequireAnyFeature(flags...)evaluate feature toggles.RequireCreationLimit(resource, checkFn)checks resource quotas on entity creation (ID == 0).ImmutableWhen(guardFn, reason)aborts execution if an entity is in a locked/terminal state.TrackPIIAccess(tracker, purpose)records personal data access reasons for regulatory compliance.Audited(logger, category, detailsFn)records audit events upon successful action execution.Transactional(runner)wraps execution inside an application-providedTxRunner.
xerr provides structured error categories to drive consistent transport mapping and retry decisions:
// Categories: BadRequest, Unauthorized, Forbidden, NotFound, Conflict,
// Validation, TooManyRequests, Timeout, Unavailable, Internal, CircuitBreaker.
return xerr.NotFound("user not found")
return xerr.Unavailable("database connection dropped", originalErr)xerr.IsTransient(err)checks whether an error is safe to retry.xerr.From(err)converts arbitrary Go errors into structured*AppErrortypes.appErr.Public(requestID)returns a sanitizedErrorResponsesuitable for API responses without leaking internal causes or stack traces.- Validation detail values are redacted; clients receive field names and validation rules without the submitted values.
xerr.Sprint(err)renders error trees with sanitized user stack traces in development (ENV=dev) and structured one-line outputs in production.
The optional observe package emits vendor-neutral lifecycle events. Sinks are concurrency-safe and receive structured observe.Event records with action Duration and complete Request/Response payload references for latency and token/cost attribution:
type fanoutSink struct{ sinks []observe.Sink }
func (f *fanoutSink) Emit(ctx context.Context, e observe.Event) {
for _, s := range f.sinks { s.Emit(ctx, e) }
}
sink := &fanoutSink{sinks: []observe.Sink{
observe.NewSlogSink(slog.Default()),
observe.NewMetricsSink(),
observe.NewPrometheusSink(),
observe.NewMemorySink(100),
observe.NewJSONLSink(os.Stdout, 4096),
}}
act := action.New("user.find", findUser).
AnyHook(observe.Hook(sink)).
Build()| Kind | Emitted When | Relevant Event Fields |
|---|---|---|
executed |
Action completes successfully | Request, Response, Duration |
error |
Action fails with an error | Error, Duration |
retry |
Retry middleware initiates another attempt | Attempt, Error, Duration |
cache_hit |
A cache layer serves the response | Request, Response, Duration |
cache_miss |
No cache layer contains the key | Request, Duration |
canceled |
Action observes caller context cancellation | Request, Duration |
panic |
Action recovers an unhandled panic | Recovered, Request, Duration |
deduplicated |
Concurrent duplicate waits on an existing flight | Request, Duration |
coalesced |
Concurrent caller receives a coalesced result | Request, Duration |
Every event includes Time, Duration, Kind, Action, and available correlation identifiers (ExecutionID, TraceID, SpanID).
- Context cancellations emit
canceledand are not duplicated aserrorevents. - Recovered panics emit a
panicevent followed by anerrorevent containing the resultingxerr.KindInternalerror. - Nil hooks and no-op sinks evaluate with zero heap allocations on the hot path.
MemorySink: Thread-safe circular ring buffer.Events()returns an isolated snapshot copy in oldest-to-newest order.MetricsSink: Aggregates counters by action name and event kind.Snapshot()returns an isolated map.PrometheusSink: Generates deterministic Prometheus exposition text with escaped labels.JSONLSink: Synchronized structured JSON writer with serialized durations. Raw error and recovered panic text are replaced with[redacted].SlogSink: Dispatches structured logs including duration through standard librarylog/slog.
The Kernel provides execution semantics and safety contracts; applications supply external integrations:
- Storage & State: Cache backends, distributed locks, idempotency stores, and database transactions are supplied via interfaces. The Kernel does not bundle concrete database drivers.
- Telemetry Ingestion:
observecaptures lifecycle events and execution duration locally. Forwarding events to OpenTelemetry collectors, Datadog, or external brokers belongs to application sinks. - Human-in-the-Loop & Workflows: The Kernel manages suspension (
dag.ErrSuspended), partial state preservation, and memoized resumption. Applications supply the human interfaces (webhooks, email dispatch, approval dashboards) and durable persistence for state snapshots. - Durable Resume Binding:
action.ExecutionIdentitybinds replay to source, input, and contract digests. A mismatch is a conflict unless the caller explicitly requests a forced successor generation with a reason. - Security Decisions: Context guards inspect metadata attached to
context.Context. Authentication (decoding JWTs, session lookups, certificate validation) is handled at transport boundaries. - Resource Ownership: Pooled objects (
dag.State,xctx.RequestScope) must be explicitly released by the caller to prevent resource leaks.
The Kernel avoids reflection on execution paths, relies on immutable structures post-build, and compiles middleware chains at initialization time.
Streaming is O(1) in memory: StreamAction[Req, T] wraps Go 1.23 iter.Seq2[T, error] under action lifecycle management. The typed Do and DoStreamTyped paths do not allocate per item; the type-erased DoStreamAny boundary boxes each item into any and can allocate for non-pointer values. A constant per-call overhead is also paid (iterator closure, hook wrappers, panic recovery).
Run the repository checks through Task, using the same targets as CI:
# Format
task fmt
# Lint and static analysis
task lint
# Run the race-enabled test gate
task test:race
# Benchmark core dispatch and allocation profiles
task bench
# Run the complete CI gate
task ciComplete, runnable examples are maintained in the central nexssp/examples repository. This repository keeps only examples/README.md as a pointer:
01_ai_dag_pipeline– Multi-layer parallel DAG execution with typed outputs.02_resilient_action– Deduplication, multi-layer caching, exponential jitter retry, and hooks.03_composition_and_fanout– Sequential pipelines (Pipe) and bounded concurrency (FanOut).04_fenced_distributed_lock_failover– Monotonic fencing token renewal and lease-loss cancellation.05_parallel_scatter_gather_recovery– Transient error recovery during parallel fan-out.06_pure_streaming_pipeline– Constant O(1) memory processing using Go 1.23+iter.Seq2.07_hierarchical_nested_dag– Embedding compiled DAGs as executable nodes within parent DAGs.08_thundering_herd_coalescing– Request coalescing under high concurrent load.09_retry_policies– Custom predicates, transient-only retries, and universal retry policies.10_observe_lifecycle– End-to-end lifecycle observation with Prometheus, Slog, JSONL, and Metrics sinks.11_lazy_etl_stream– Lazy ETL over typed streams with bounded memory.12_stream_action_crossover– Crossing typed actions and streams.13_resilient_mod_host– Host-owned resilience and module integration.
v1.0.0-rc1 is a release candidate for 1.0. The exported API is considered feature-complete: until v1.0.0, only fixes for blocking defects are expected, and any API change will be called out in the CHANGELOG. Please try the candidate and report problems through GitHub issues.
From v1.0.0 the module follows Semantic Versioning: no breaking changes to exported APIs within v1.x. Symbols marked Deprecated: keep working for the lifetime of v1. Prior to 1.0 (v0.x), exported APIs could change between minor releases.
Pre-release versions are never selected automatically by go get; opt in explicitly:
go get github.com/nexssp/kernel@v1.0.0-rc1Pin an explicit version rather than tracking main.
Read CONTRIBUTING.md before opening a pull request. Changes must be typed, covered by tests, and include benchmarks for performance-critical paths.
Report suspected vulnerabilities privately according to SECURITY.md.
Apache License 2.0. See LICENSE.
Copyright © 2018–2026 Marcin Polak and Contributors.