- Docs
- Reference
- API index
API index
Package entry points with container accessors for every service.
Battery interfaces live in core/<b> with the Register/Open registry, each adapter lives in its own module at adapters/<b>/<a> with a Register() call wiring it in, and SDK-free helpers live in shared/*. Import the core interface plus the adapter modules you need and resolve through container. The dsl/* packages are internal-only: runtime code must not import the compiler.
Construct and resolve
Section titled “Construct and resolve”Construction is always config plus container. Each service resolves on first use and caches the result; on error the cached state clears so the next call retries.
import ( "github.com/zenta-dev/zever/config" "github.com/zenta-dev/zever/container")
c := container.New(config.Default())db, err := c.DB()if err != nil { return err}q, err := c.Queue()if err != nil { return err}d, err := c.Job() // d shares the resolved queue instanceif err != nil { return err}container.New(nil) is valid: an untouched container closes cleanly without opening anything. Job() has no registry of its own; it builds a *job.Dispatcher over the already-resolved Queue. Scheduler() injects that dispatcher, so the scheduler shares the same Queue connection instead of opening a redundant one. Resolving Scheduler() therefore resolves Job() and, transitively, Queue as a side effect.
GRPCClient(target, opts...) builds *grpc.ClientConn connections through the shared/grpcclient helper (round-robin LB, retry policy, TLS, static resolver) and caches one conn per target string; the conns close with the container.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel()if err := c.Close(ctx); err != nil { var te *container.CloseTimeoutError var pe *container.ClosePanicError _ = te _ = pe return err}Close shuts down only resolved services, dependents first, joining per-service close failures via errors.Join.
Core packages
Section titled “Core packages”| Package | Role |
|---|---|
config |
layered typed config, defaults/file/env (own module) |
container |
sole resolver, lazy accessors, ordered close (own module) |
orm |
generics typed builder over core/db (own module) |
dsl |
.zen compiler frontend, compile time only (own module) |
core/middleware |
shared HTTP middleware (own module) |
cmd/zever |
flags-only toolkit shell (own module) |
shared/* |
SDK-free helpers (codec, redisclient, redisopt, s3opts, retry, lrucache, …), one module each |
shared/grpcclient |
gRPC client constructor (New(ctx, target, opts...): LB, retry, TLS, static resolver); no registry, resolved via GRPCClient(target, opts...) |
Service packages and accessors
Section titled “Service packages and accessors”| Package | Accessor | Notes |
|---|---|---|
core/agent |
Agent() |
*agent.Loop |
core/ai |
AI() |
|
core/analytics |
Analytics() |
|
core/auth |
Auth() |
|
core/billing |
Billing() |
|
core/cache |
Cache() |
leaf dependency, closed last |
core/cdn |
CDN() |
|
core/crypto |
Crypto() |
|
core/db |
DB() |
plus Transactor() helper |
core/document |
Document() |
|
core/eventbus |
EventBus() (Eventbus() alias) |
|
core/flag |
Flag() |
|
core/geo |
Geo() |
|
grpc |
GRPC(opts...) |
lazy *grpc.Server singleton, no registry |
core/i18n |
I18n() |
|
core/idempotency |
Idempotency() |
|
core/job |
Job() |
*job.Dispatcher over resolved Queue |
core/lock |
Lock() |
|
core/log |
Log() |
|
core/mailer |
Mailer() |
|
core/media |
Media() |
|
core/notification |
Notification() |
|
core/observability |
Observability() |
|
core/outbox |
Outbox() |
|
core/password |
Password() |
|
core/payment |
Payment() |
|
core/permission |
Permission() |
|
core/queue |
Queue() |
leaf dependency, closed last |
core/rag |
RAG() |
*rag.Engine |
core/ratelimit |
RateLimit() (Ratelimit() alias) |
|
core/resilience |
Resilience() |
|
core/router |
Router() |
|
core/scheduler |
Scheduler() |
shares Queue via Job(), closed first |
core/search |
Search() |
|
core/secrets |
Secrets() |
|
core/session |
Session() |
|
core/storage |
Storage() |
|
core/tenant |
Tenant() |
|
core/vectorstore |
VectorStore() |
|
core/webhook |
Webhook() |
|
core/workflow |
Workflow() |
Close shapes
Section titled “Close shapes”| Shape | Used by | Semantics |
|---|---|---|
Close(ctx) |
pooled or network-backed services that may block (db, cache, storage, lock, container itself) |
context-bounded shutdown |
Close() |
lightweight handles, iterators, statements, instant-close in-memory adapters (auth, queue, session, payment, eventbus.Pusher, ratelimit.Limiter, db.Rows, db.Stmt) |
instant close |
Stop() |
scheduler only | cron lifecycle stop |
Probing (closeAny) tries Close(context.Context) error, then Close() error, then Stop() error, then Shutdown(context.Context) error (observability providers flush buffered spans/metrics), then no-op nil (*job.Dispatcher has no shutdown method). Crypto, log, password, permission, and router declare no Close/Stop/Shutdown and probe as no-op nil. Callers never guess: the probe picks the shape.
Close order:
scheduler, job dependents holding a queue ref, firstsnapshots everything without explicit orderingcache, queue leaf dependencies, lastdb, registry pools shared pools, after every borrower (no use-after-close)grpcServer independent GracefulStop/Stop, bounded by ctxgrpc clients independent, one conn per target, closed with the containerPer-service bound is 5s only when the parent context carries no deadline; otherwise the parent deadline bounds each wait. Shared instances close once (pointer-identity dedup with a keepAlive set for the duration). Failures join via errors.Join; panics become *ClosePanicError, timeouts become *CloseTimeoutError. Error values name the service only, never resolved values. Close never opens anything: untouched services stay untouched.
Production notes
Section titled “Production notes”- Start from
config.Default()+container.New, then per-service accessors; no globals, noinit()wiring. - Keep to documented interfaces; new behavior means new interfaces, never new methods on public ones.
- Pass a parent deadline to
Closein servers so shutdown is bounded end to end; inspectCloseTimeoutError/ClosePanicErrorwitherrors.As. - Goroutine-safe types document their exit path; resolve the in-memory subset and
Closeit in tests sogoleakstays clean.
Troubleshooting
Section titled “Troubleshooting”- Close hangs: parent context has no deadline and a service blocks; pass a timeout context (per-service bound is 5s only without one).
- Close reports
CloseTimeoutError: a service outlived its bound. Check which service is named, then its backing store health. - Close reports
ClosePanicError: a service panicked during shutdown. Fix the service; the panic value is captured, not re-thrown. - Accessor keeps failing: cached state clears on error, so each call retries fresh. Persistent failure means config or backend, not the container; check
Validateand connectivity.
Related
Section titled “Related”- Adapters matrix for adapter choice per service.
- Config reference for values behind accessors.
- CLI reference for runtime commands over the container.