quarkbridge

package module
v1.8.24 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

quarkbridge

github.com/jcsvwinston/orbit/quarkbridge

Framework floor. This module builds against Nucleus and moves in lockstep with the certified suite set. The exact version it requires is in this module's go.mod — that file is the source of truth, so this note cannot go stale.

An opt-in Quark middleware that publishes the SQL statements a Quark client executes onto a Nucleus observability feed, so they appear in Orbit's live SQL view — correlated to the originating HTTP request.

Why it exists

Orbit's live SQL view drains Nucleus's event bus (nucleus.EventBus.SubscribeSQL). The framework's own CRUD layer already feeds that bus, but an application that runs its queries through the Quark ORM instead does not — those statements never reach the feed. This bridge closes that gap without teaching Orbit about Quark or Quark about Nucleus: it maps each executed statement to a nucleus.SQLEvent and publishes it through Nucleus's public SQL ingest (EmitSQL, Nucleus ADR-020), which Orbit already consumes.

It is deliberately a separate, opt-in module that depends on both Quark and Nucleus — it does not belong in either product's core (suite decision QADR-0006).

Usage

import (
    "github.com/jcsvwinston/orbit/quarkbridge"
    "github.com/jcsvwinston/quark"
)

// rt is the nucleus.Runtime handed to your module's OnStart hook.
bridge := quarkbridge.New(rt.Observability())

client, err := quark.New("pgx", dsn, quark.WithMiddleware(bridge))

Every statement client runs is now timed, mapped, and published to the live feed. rt.Observability() returns a nucleus.EventBus, which satisfies the bridge's SQLSink directly.

Request correlation

RequestID, TraceID, and UserID are read from the context.Context Quark threads through the middleware, using Nucleus's own context helpers (pkg/observe). This is why the bridge is a quark.Middleware (which receives ctx) and not a quark.QueryObserver (which does not): without ctx the feed would lose the link to the request.

ModelName is left empty — the model/table name is available to Quark's QueryObserver, not to a middleware, which sees only the rendered SQL. Operation is derived from the leading SQL keyword (SELECT/INSERT/…).

Redaction

By default (RedactArgs) bind arguments are masked the same way Nucleus masks its own SQL feed: string and []byte values become type(len):*** markers, while numeric, bool, time.Time, and nil values are kept verbatim (so a WHERE id = ? key still reads as e.g. 42). Bridged statements therefore render consistently alongside framework ones.

Opt into raw values for local debugging only:

bridge := quarkbridge.New(rt.Observability(), quarkbridge.WithRedaction(quarkbridge.IncludeArgs))

WithNodeID("...") tags events with the framework process id, matching the NodeID Nucleus's own observer stamps.

Relationship to OpenTelemetry

OTel (quark/otel) is complementary, not the transport for this feed: its spans are exported in batch for durable tracing and would not be real time. Run both if you want durable traces too — sharing the same tracer nests Quark's spans under the request span — but the live feed goes through this bridge.

Status

Pre-1.0, alongside Orbit. Its Nucleus dependency is pinned to a line that exposes the public SQL ingest (EmitSQL), which is newer than the pseudo-version the rest of orbit/* pins today; see the module's go.mod.

Documentation

Overview

Package quarkbridge publishes the SQL statements a Quark ORM client executes onto a Nucleus observability feed, so they show up in Orbit's live SQL view correlated to the originating HTTP request.

It is an opt-in Quark Middleware. Wire it into a *quark.Client and point it at the Nucleus event bus (rt.Observability(), which returns a nucleus.EventBus):

bridge := quarkbridge.New(rt.Observability())
client, err := quark.New("pgx", dsn, quark.WithMiddleware(bridge))

Every statement the client runs is then timed, mapped to a nucleus.SQLEvent, and published through the framework's public SQL ingest (EmitSQL, ADR-020) — the same feed Orbit already drains via SubscribeSQL. No change to Orbit and no change to either product core is required (QADR-0006): the bridge depends on both Quark and Nucleus and lives outside their cores.

Correlation

RequestID, TraceID and UserID are read from the ctx that Quark threads through the middleware, using Nucleus's own context helpers. That is why the bridge is a Middleware (which receives ctx) rather than a QueryObserver (which does not) — without ctx the feed would lose the link to the request.

Model names

Quark has no model registry the bridge could consult, and a Middleware sees only the rendered SQL, so ModelName is derived from the statement's primary table (FROM/INTO/UPDATE/DELETE FROM). That is the TABLE name, which is what the fleet's sql_models filter then matches for bridged statements; map tables to your own model names with WithModelNames when they differ. Statements without a recognisable table (DDL, CTE-first queries) carry an empty ModelName, exactly as before.

Redaction

By default bind arguments are masked exactly the way Nucleus masks its own SQL feed: string and []byte values become "type(len):***" markers, while numeric, bool, time.Time and nil values are kept verbatim (so a "WHERE id = ?" key still reads as e.g. "42"). Opt into raw values with WithRedaction(IncludeArgs) for local debugging only — it applies no scrubbing.

OTel

OpenTelemetry (quark/otel) is complementary, not the transport for this feed: its spans are exported in batch for durable tracing and would not be real time. This bridge is the live-feed path; run both if you want durable traces too, sharing the same tracer so Quark's spans nest under the request span.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Middleware

type Middleware struct {
	// contains filtered or unexported fields
}

Middleware is a quark.Middleware that publishes executed SQL to a Nucleus feed. Construct it with New and pass it to quark.WithMiddleware. It is safe for concurrent use: it holds only immutable configuration.

func New

func New(sink SQLSink, opts ...Option) *Middleware

New returns a Middleware that publishes to sink. A nil sink makes every wrapped call a straight pass-through (the bridge emits nothing), so wiring the bridge without a live feed is harmless.

func (*Middleware) WrapExec

func (m *Middleware) WrapExec(next quark.ExecFunc) quark.ExecFunc

WrapExec implements quark.Middleware. It times the execution and publishes the statement (with any error) after next returns.

func (*Middleware) WrapQuery

func (m *Middleware) WrapQuery(next quark.QueryFunc) quark.QueryFunc

WrapQuery implements quark.Middleware for row-returning queries.

func (*Middleware) WrapQueryRow

func (m *Middleware) WrapQueryRow(next quark.QueryRowFunc) quark.QueryRowFunc

WrapQueryRow implements quark.Middleware for single-row queries. The error is read from (*sql.Row).Err, which reports a failure of the underlying query before Scan is called.

type Option

type Option func(*Middleware)

Option configures a Middleware.

func WithModelNames

func WithModelNames(tableToModel map[string]string) Option

WithModelNames maps table names (as they appear in SQL, matched case-insensitively) to the model names published on events. Tables absent from the map publish their table name.

func WithNodeID

func WithNodeID(id string) Option

WithNodeID tags published events with the framework process identifier. It matches the NodeID Nucleus's own observer stamps; leave it unset for local development (NodeID may be empty).

func WithRedaction

func WithRedaction(mode RedactionMode) Option

WithRedaction sets how bind arguments are exposed. The default is RedactArgs.

type RedactionMode

type RedactionMode int

RedactionMode controls whether bind arguments are exposed on published events. It mirrors the redaction principle Quark applies to its OTel spans.

const (
	// RedactArgs is the default. String and []byte argument values are masked
	// as "type(len):***"; numeric, bool, time.Time and nil values are kept
	// verbatim — the same convention Nucleus uses for its own SQL feed, so
	// bridged statements render consistently alongside framework ones.
	RedactArgs RedactionMode = iota

	// IncludeArgs places raw argument values on the event via fmt.Sprintf("%v",
	// arg), with no scrubbing. Opt in only for local debugging.
	IncludeArgs
)

type SQLSink

type SQLSink interface {
	EmitSQL(nucleus.SQLEvent)
}

SQLSink is the minimal ingest the bridge publishes to. A nucleus.EventBus (returned by nucleus.Runtime.Observability()) satisfies it via EmitSQL, so a caller passes that value directly; tests can pass a lightweight fake.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL