api

package module
v1.0.0-alpha.21 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

README

Universal Ferret API

Portable contracts for compiled execution and retained source-level debugging. Implementations own engine configuration; consumers share Runtime, reusable Plan, per-run Session, and the types in source, result, debugger, and diagnostics.

Execution and ownership

Runtime.Compile and CompileDebug finish compilation before returning a plan. Syntax and compiler errors are immediate. Plans support repeated and concurrent sessions with independent parameters and filesystem configuration. Plan.Params(ctx) ([]string, error) returns a caller-owned snapshot of parameter names or a metadata retrieval error. An empty list with a nil error means the plan has no parameters; it is distinct from a retrieval failure.

Runtime.Version(ctx) (Version, error) reports the version of the runtime implementation represented by that Runtime. A remote adapter reports the remote runtime's version. This is separate from the embedding application's, CLI's, daemon/server's, or transport protocol's version. Version is an opaque string-backed value whose String() method preserves the implementation-provided value unchanged. Values such as v2.0.0-alpha.55, 2.0.0, dev, and unknown are valid; UAPI does not parse, normalize, or validate them as semantic versions.

Both metadata operations may fail and may require remote I/O. Local implementations may return immediately. UAPI imposes no transport-specific behavior or caching requirements.

Each object releases the resources it owns. Owning runtimes reject subsequent work according to their closed-state semantics. Borrowing adapters may document a no-op Close that leaves the adapter and underlying runtime usable; the underlying owner remains responsible for cleanup.

Plan closure prevents subsequent session and debug-session creation. It does not implicitly close or cancel already-created sessions or debug sessions. Returned descendants remain responsible for their own lifecycle. Parent closure does not implicitly cancel caller-owned operations and need not wait for operations or constructors already started. Callers coordinate outstanding work and cleanup when descendants use parent-owned resources.

Close is idempotent and retains the completed cleanup result, without requiring identical error-wrapper pointers. Ordinary execution owners cancel and settle running work and its output before reusing or closing the session, unless the implementation explicitly supports a stronger contract. Debugger session closure terminates and settles active commands.

Runtime.Run and Session.Run return (Output, error). A successful Run obtains a usable, caller-owned handle; it does not certify execution or delivery success. Execution starts before the handle is returned and is not deferred until consumption. Admission/preparation failures return a nil handle and an error, preserving cleanup failures for resources acquired before failure. Implementations must not return a usable handle alongside a Run error, a typed-nil handle, or (nil, nil).

Once a usable handle is returned, terminal execution, encoding, delivery, and output-owned cleanup errors are reported through Consume or Collect. The handle is usable even when no content is ultimately available. Callers running scripts only for side effects must still consume output to observe completion. Close is abandonment; its success does not certify successful execution.

Runtime.Run owns its temporary session and plan. Resources still needed by output transfer to that output and are finalized by consumption or closure. Resources already independent of consumption may be released earlier. Session.Run output never closes the caller-owned session. These rules do not introduce cascading parent closure.

Consumable output

The result package defines Output, Content, Metadata, and Consumer, also exported as root api aliases:

Runtime.Run / Session.Run -> Output
                              Consume: receive borrowed encoded chunks
                              Collect: obtain detached *Content
                              Close: abandon and release owned resources

Output.Metadata() returns immutable, local metadata without I/O, including during consumption and after closure. Run establishes it before exposing the handle without waiting for or buffering the complete payload solely to determine length. ContentType identifies the encoded representation. When LengthKnown is true, Length is the nonnegative, exact total encoded payload byte count, not records, transport frames, remaining bytes, or progress. Unknown length is normal. Known zero length does not establish presence, and advertised length must not require unrestricted preallocation.

Consume and Collect are alternative one-shot terminal operations. Admission validates a non-nil context, then a non-nil consumer for Consume, then already-canceled consumption and invocation contexts, before atomically claiming the handle. Invalid or rejected calls do not claim it or disrupt another consumer. A rejected consumption context may be retried within the invocation's lifetime. Once admitted, an operation cannot be resumed or repeated; failure or cancellation finalizes its owned resources before return.

Valid competing consumption calls match result.ErrInUse while delivery is active and stopping has not begun. After closure or finalization begins, new valid calls match result.ErrClosed. Root convenience exports api.ErrOutputInUse and api.ErrOutputClosed reference those same sentinel values. Use errors.Is; wrappers and joined failures are allowed. There is no separate consumed or finalized error.

Close abandons unread output without silently draining arbitrarily large payloads. During active consumption it requests cancellation and waits for the callback and cleanup. If explicit closure wins before the terminal outcome is committed, the active operation matches ErrClosed, preserving other observed failures. Closure after commitment waits for cleanup without changing that outcome. Automatic finalization does not add ErrClosed to the original result; caller-context cancellation retains its context error. Repeated or concurrent Close calls return the recorded cleanup outcome, usually nil, rather than a lifecycle error simply because the output was already closed.

Callbacks are synchronous, ordered, and non-overlapping. No callback remains active or is invoked after Consume returns. Chunks are borrowed, read-only byte slices valid only during the callback; copy retained bytes. Boundaries need not align with JSON values, lines, records, or characters. Empty chunks are not EOF. A callback error stops further delivery and initiates finalization. Panic unwinding also finalizes resources without swallowing the panic; cleanup failures remain available through Close.

Metadata reads are safe concurrently and from callbacks. Reentrant consumption is rejected under the same admission rules. A callback must not call Close synchronously on its own output because Close waits for that callback. Cancellation cannot forcibly interrupt arbitrary callback code or release borrowed buffers still in use.

The invocation context bounds the output's lifetime after Run returns. A consumption context may shorten that lifetime, not extend or revive it. The effective context passed to callbacks observes cancellation from either context and their earliest deadline. Keep any locally created invocation context alive until output is settled; do not defer its cancellation in a helper that returns a live handle.

Content presence and errors

Content is detached, recipient-owned data that survives output closure. Inspect available content independently of the collection error:

Situation Collect Consume
Absent content nil content No callback
Present empty content Non-nil *Content, even with nil Data At least one empty chunk
Available content plus terminal error Content and error together Delivered bytes and terminal error
Failure after receiving a prefix Prefix and error together Delivered prefix and error

Neither zero length, nil Data, nor empty content type is an absence sentinel. Content.Metadata preserves the complete-payload descriptor even after partial failure; len(Content.Data) counts bytes actually collected. An otherwise complete delivery or collection that mismatches a known length must return an error. Joined errors preserve execution, consumer, and cleanup causes through standard Go error traversal.

Consumable delivery permits bounded buffers and reuse without requiring incremental query evaluation or native encoding. A buffered adapter may transfer suitable detached owned bytes directly from Collect; a generic chunk accumulator or another copy is not required. Detached content must not alias borrowed or reusable implementation buffers.

Collecting

This helper returns available content even when collection fails. Fallback closure also preserves cleanup failures; Close is idempotent after collection. These examples use only the portable API and have compiling counterparts in output_example_test.go.

package example

import (
    "context"
    "errors"
    "fmt"

    "github.com/MontFerret/api"
)

func collectQuery(ctx context.Context, runtime api.Runtime, src api.Source) (content *api.Content, err error) {
    output, err := runtime.Run(ctx, src)
    if err != nil {
        return nil, err
    }
    defer func() { err = errors.Join(err, output.Close()) }()
    return output.Collect(ctx)
}

func inspectQuery(ctx context.Context, runtime api.Runtime, src api.Source) error {
    content, err := collectQuery(ctx, runtime, src)
    if content != nil {
        fmt.Printf("%s: %q\n", content.Metadata.ContentType, content.Data)
    }
    return err
}
Forwarding chunks

The destination handles each borrowed chunk synchronously. Destination errors stop delivery; a short write without an error becomes io.ErrShortWrite. This helper retains no payload. A destination may choose to buffer it, write a file, or forward it elsewhere.

package example

import (
    "context"
    "errors"
    "io"

    "github.com/MontFerret/api"
)

func streamQuery(ctx context.Context, runtime api.Runtime, src api.Source, dst io.Writer) (err error) {
    output, err := runtime.Run(ctx, src)
    if err != nil {
        return err
    }
    defer func() { err = errors.Join(err, output.Close()) }()
    return output.Consume(ctx, func(ctx context.Context, chunk []byte) error {
        if err := ctx.Err(); err != nil {
            return err
        }
        n, err := dst.Write(chunk)
        if err != nil {
            return err
        }
        if n != len(chunk) {
            return io.ErrShortWrite
        }
        return nil
    })
}

For side-effect-only execution, consume with a callback that returns nil without retaining bytes. Observe the consumption error; merely closing the handle abandons it.

Non-nil caller contexts control cancellation of Run, Compile, CompileDebug, NewSession, NewDebugSession, Plan.Params, and Runtime.Version. All of these operations require a non-nil context. Cancellation errors preserve context.Canceled and context.DeadlineExceeded through errors.Is. Parent Close does not require deriving operation contexts to coordinate descendants. Implementations may use internal contexts for their own resources and may translate portable option callbacks before validating the operation context.

Options

Session options target an implementation of SessionOptions, which may apply settings directly or queue implementation-specific options. Non-nil callbacks run exactly once in order, and their returned errors are joined. Later options can override earlier values; parameter maps merge. Runtime-specific extensions validate their target explicitly.

Portable or application-level errors may be returned immediately by an option callback. Runtime-specific conversion and validation may be deferred until the setting is used. This includes host-parameter conversion, output codecs, filesystem-root construction, and runtime-specific capabilities. A nil setter error therefore does not certify runtime validity.

Invalid settings must fail the operation no later than their relevant point of use. Implementations need not preflight all session configuration before compilation, resource acquisition, or execution. Runtime.Run may compile, create a session, then execute. Output codec availability may be validated during result encoding, after the query has run. Implementations document validation timing and when mutable inputs are converted or snapshotted. WithOutputContentType and SetOutputContentType retain their names. The selected representation is reported by Output.Metadata().ContentType; encoding failures after a usable handle is returned are observed through Consume or Collect.

WithOptimizationLevel rejects values outside the portable enum during callback application. Each runtime defines which known optimization levels it supports and any restrictions for debug compilation.

Portable data

Native Ferret produces one-based lines and byte columns, with zero-based, half-open byte spans. Source names are identities and need not be filesystem paths; anonymous sources have an empty name. Adapters translate native indexed source text into the portable Source representation. Portable coordinates, debugger values, variables, frames, breakpoints, and reasons retain their existing representations. Encoded content uses the new nested metadata shape described below. Debugger events retain their field names, including output, whose value is materialized *Content.

debugger.ValueReference.Valid accepts positive references. References are scoped to a paused state and become stale when execution resumes. debugger.NoFunction identifies the top-level program body. Compiler table identifiers and validation remain implementation details.

Debugger commands are StepIn, StepOver, and StepOut. Breakpoint requests use canonical source locations and binding options. ReplaceBreakpoints(ctx, sourceName, requests) replaces a source's complete set atomically, including during execution; an empty request slice clears it. Each BreakpointRequest contains a position and binding options. Results preserve request order and distinguish unbound locations from operation failure. Failure before publication leaves the prior set intact. A stop already decided before removal remains inspectable with its original hit IDs. Incremental add/delete methods remain available and observe their request context through publication; canceling a breakpoint request does not cancel the debuggee. All debugger methods except Close take a non-nil context, including Pause, breakpoint listing, and inspection. Inspection checks cancellation before and after command admission; cancellation need not interrupt the admission wait. A canceled pause request must not request a stop.

Breakpoints(ctx) ([]Breakpoint, error) returns a detached, ID-ordered snapshot, including after Close. Nil and canceled contexts return errors. Metadata and listing errors can be reported without conflating failure with an empty result.

A completed event and its detached content can accompany a later cleanup error. Retained events and snapshots must not store live output handles or mutable implementation buffers; their bytes remain readable after debugger cleanup. Inspecting one observer's event cannot consume another observer's data. Recipients coordinate mutations of shared materialized content themselves. Error projections should preserve each diagnostic's source, annotation order, joined branches, and native causes through standard Go error traversal. Event.Error remains a Go error; this change defines no portable JSON error codec. Adapters continue to own serialized error projections.

Migration from materialized output

This is an intentional breaking change to both the Go API and encoded-content JSON:

Previous API Current API
Materialized result.Output / api.Output struct Detached result.Content / api.Content struct
Run(...) (*Output, error) Run(...) (Output, error), followed by Consume or Collect
output.ContentType output.Metadata().ContentType or content.Metadata.ContentType
Materialized payload field Content Content.Data
Flat contentType and content JSON keys Nested metadata object and data key
Execution/cleanup result observed at Run return Handle admission at Run; terminal result through consumption
Debugger event Output containing old output struct Same field/key containing detached *Content

For example, populated materialized content serializes as:

{"metadata":{"contentType":"application/json","length":2,"lengthKnown":true},"data":"NDI="}

Payload bytes use standard base64 byte-slice encoding; they are not interpreted as a JSON document. A nil *Content serializes as null. A present content object with nil Data has "data":null; a non-nil empty byte slice has "data":"". All descriptor fields remain present, including unknown length. Old JSON keys are not emitted. Live output handles must not be serialized, and marshaling must never consume them.

Documentation

Overview

Package api defines implementation-independent contracts for compiling, executing, and debugging Ferret queries.

Runtime.Run and Session.Run return caller-owned, one-shot Output handles. A successful Run obtains a usable handle; Consume or Collect observes terminal execution, delivery, and cleanup errors. Close abandons unread output. Invocation contexts remain in effect until output is settled. Output.Metadata is immutable and local; Content is detached materialized data, also used by debugger events. See result.Output for consumption, presence, cancellation, and closure contracts.

Plan.Params and Runtime.Version retrieve metadata and may involve remote I/O. Both require non-nil caller contexts, and cancellation errors must preserve context.Canceled and context.DeadlineExceeded through errors.Is. The API imposes no transport-specific behavior or caching requirements.

Plan.Params returns a caller-owned snapshot; an empty parameter list is distinct from a metadata retrieval error. Runtime.Version returns an opaque Version for the represented runtime implementation, including the remote runtime for a remote adapter, rather than the host application, CLI, server, or transport.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrOutputInUse is result.ErrInUse. Use errors.Is to identify a consumption
	// attempt rejected because another consumer owns the output.
	ErrOutputInUse = result.ErrInUse

	// ErrOutputClosed is result.ErrClosed. Use errors.Is to identify consumption
	// rejected after stopping begins, or interrupted by an explicit Close that
	// wins before outcome commitment. Close itself returns its cleanup outcome.
	ErrOutputClosed = result.ErrClosed
)

Functions

This section is empty.

Types

type Consumer

type Consumer = result.Consumer

Consumer receives borrowed, read-only chunks during Output.Consume. Copy retained bytes; see result.Consumer for callback and context requirements.

type Content

type Content = result.Content

Content is detached, caller-owned encoded data returned by Output.Collect or retained debugger events. A nil *Content means no content is available; a non-nil pointer, including &Content{}, means present content. See result.Content.

type Location

type Location = source.Location

Location represents the location of a specific point in a source file, including the file name and position.

type Metadata

type Metadata = result.Metadata

Metadata describes the complete encoded payload independently of content presence. See result.Metadata for length and immutability requirements.

type OptimizationLevel

type OptimizationLevel int
const (
	OptimizationNone OptimizationLevel = iota
	OptimizationBasic
	OptimizationFull
	OptimizationAggressive
)

type Output

type Output = result.Output

Output is the caller-owned, one-shot consumable handle returned by execution. Consume or Collect observes completion and finalizes resources; Close abandons unread output. See result.Output for lifetime, presence, and error requirements.

type Plan

type Plan interface {
	io.Closer

	// Params returns a caller-owned snapshot of the plan's parameter names.
	// An empty list with a nil error means the plan has no parameters; failure
	// to retrieve metadata returns an error.
	//
	// ctx must be non-nil. Cancellation errors must preserve context.Canceled
	// and context.DeadlineExceeded through errors.Is. Retrieval may involve
	// remote I/O; local implementations may return immediately. UAPI imposes
	// no transport-specific behavior or caching requirements.
	Params(ctx context.Context) ([]string, error)
	NewSession(ctx context.Context, opts ...SessionOption) (Session, error)
	NewDebugSession(ctx context.Context, opts ...SessionOption) (debugger.Session, error)
}

Plan represents a compiled program. Compilation finishes before a plan is returned. Plans support independent sessions and are not consumed by execution.

Close releases plan-owned resources and prevents subsequent session and debug-session creation. It is idempotent and retains its cleanup result, without requiring identical error-wrapper pointers. Close need not wait for constructors already started. It does not implicitly close or cancel returned sessions or debug sessions; callers remain responsible for their lifecycle.

Params, NewSession, and NewDebugSession use non-nil caller contexts for cancellation. Close does not cancel those contexts. Callers coordinate work and cleanup when sessions use plan-owned resources.

type PlanOption

type PlanOption = func(PlanOptions) error

func WithOptimizationLevel

func WithOptimizationLevel(level OptimizationLevel) PlanOption

WithOptimizationLevel sets the optimization level for the execution plan. The callback rejects unknown enum values before invoking the target setter; the runtime determines which known levels it supports.

type PlanOptions

type PlanOptions interface {
	SetOptimizationLevel(OptimizationLevel) error
}

type Position

type Position = source.Position

Position represents a specific point in a source file, defined by line and column numbers.

type Range

type Range = source.Range

Range represents a range of characters in a source file, including the location and span.

type Runtime

type Runtime interface {
	io.Closer

	// Version reports the version of the runtime implementation represented by
	// this Runtime. A remote adapter reports its remote runtime's version, not
	// the version of the host application, CLI, daemon/server, or transport protocol.
	//
	// ctx must be non-nil. Cancellation errors must preserve context.Canceled
	// and context.DeadlineExceeded through errors.Is. Retrieval may involve
	// remote I/O; local implementations may return immediately. UAPI imposes
	// no transport-specific behavior or caching requirements.
	Version(ctx context.Context) (Version, error)

	// Run starts execution and returns a usable, caller-owned Output with nil
	// error. Success means a handle was obtained, not that execution or delivery
	// completed. Execution is not deferred until consumption. Metadata is reliable
	// before return without buffering solely to determine length.
	//
	// Admission or preparation failures return nil output and an error, preserving
	// cleanup failures for resources already acquired. Never return a usable handle
	// alongside a Run error or use a typed-nil implementation as an absent handle.
	// Once a handle is returned, terminal execution, encoding, delivery, and
	// output-owned cleanup errors are reported by Consume or Collect, preserving
	// available content. Even absent content is observed through a usable handle.
	//
	// ctx must be non-nil and bounds the output's lifetime after return. Callers
	// must not cancel it before settling the output. Consume or Collect finalizes
	// resources; Close abandons unread output without certifying completion.
	// Side-effect-only callers must consume to observe completion. See Output.
	Run(ctx context.Context, src Source, opts ...SessionOption) (Output, error)
	Compile(ctx context.Context, src Source, opts ...PlanOption) (Plan, error)
	CompileDebug(ctx context.Context, src Source, opts ...PlanOption) (Plan, error)
}

Runtime compiles source into reusable plans. Callers own directly created plans and sessions and are responsible for their cleanup.

Close releases implementation-owned resources and is idempotent, retaining its cleanup result without requiring identical error-wrapper pointers. Owning runtimes reject subsequent work according to their closed-state semantics. Borrowing adapters may document a no-op Close that leaves the adapter and underlying runtime usable. Close does not implicitly cancel caller-owned work and need not wait for operations already started.

Run, Compile, CompileDebug, and Version use non-nil caller contexts for cancellation. Callers coordinate work and cleanup when descendants use parent-owned resources. Run owns its temporary session and plan; resources needed for consumption transfer to the returned Output, which finalizes them. Resources independent of consumption may be released earlier. Caller-owned descendants and borrowed parents retain their existing ownership.

type Session

type Session interface {
	io.Closer

	// Run starts execution and returns a usable Output with nil error, rather than
	// certifying execution or delivery success. Execution is not deferred until
	// consumption. Metadata is reliable before return without buffering solely
	// to determine length.
	//
	// Admission or preparation failures return nil output and an error, preserving
	// cleanup failures for resources acquired by this invocation. Never return a
	// usable handle alongside an error or represent absence using a typed nil.
	// After a handle is returned, terminal execution, encoding, delivery, and
	// output-owned cleanup errors belong to Consume or Collect, alongside any
	// available content. An absent payload still has a usable output handle.
	//
	// ctx must be non-nil and bounds the output's lifetime after return. Keep it
	// alive until the output is settled. Consume or Collect observes completion
	// and finalizes output-owned resources without closing this session. Close on
	// the output abandons it; side-effect-only callers must consume. See Output.
	Run(ctx context.Context) (Output, error)
}

Session executes a compiled plan with per-session configuration. Run observes its non-nil context and returns a caller-owned consumable Output. Unless a stronger implementation contract explicitly allows otherwise, callers serialize Run and settle its output before reusing or closing the session. Output cleanup never closes this caller-owned session. Close is idempotent and retains its cleanup result, without requiring identical error-wrapper pointers.

type SessionOption

type SessionOption = func(SessionOptions) error

SessionOption applies portable or application-specific session configuration. Implementations invoke non-nil callbacks once in order and join their returned errors. Callbacks may return errors immediately; runtime-specific validation may instead fail in the operation that uses the setting. See SessionOptions.

func WithFSRoot

func WithFSRoot(root string) SessionOption

WithFSRoot selects the rooted filesystem used by one execution session. The runtime defines path validation and owns any filesystem resources created for the session. Validation and construction may occur when the root is applied.

func WithOutputContentType

func WithOutputContentType(contentType string) SessionOption

WithOutputContentType selects the output codec content type for session results. Codec availability may be checked when output is encoded, after query execution. The selected representation is described by Output.Metadata().ContentType; encoding failures after a usable handle is returned belong to Consume or Collect.

func WithParam

func WithParam(key string, value any) SessionOption

WithParam sets a session parameter for the execution. The runtime owns conversion and validation of the host value.

func WithParams

func WithParams(params map[string]any) SessionOption

WithParams merges the provided parameter map into the session environment, overriding existing keys while preserving any other previously defined parameters. The runtime defines when values are converted or snapshotted.

type SessionOptions

type SessionOptions interface {
	SetParam(string, any) error
	SetParams(map[string]any) error

	// SetOutputContentType selects the encoded representation's media type,
	// reported by Output.Metadata().ContentType. Codec availability may be
	// validated during encoding and then reported through output consumption.
	SetOutputContentType(string) error

	SetFSRoot(string) error
}

SessionOptions configures a session directly or queues implementation options. Setters may report portable or application-level errors immediately and defer runtime-specific conversion and validation until the setting is used. A nil setter error does not certify that the runtime can use the value.

Invalid settings must fail the operation no later than their relevant point of use. Validation need not precede compilation, resource acquisition, or all query execution. Content codec availability may be checked during result encoding, after the query has run. Implementations document validation and mutable-input conversion or snapshot timing.

Later setters override earlier values; SetParams merges keys. Runtime-specific options reject incompatible targets.

type Source

type Source = source.Source

Source represents the input data for a Ferret query.

func NewAnonymousSource

func NewAnonymousSource(content string) Source

NewAnonymousSource creates a new anonymous Source instance with the given content.

func NewSource

func NewSource(name, content string) Source

NewSource creates a new Source instance with the given name and content.

type Span

type Span = source.Span

Span represents a range of characters in a source file, defined by start and end positions.

type Version

type Version string

Version is an opaque, implementation-provided runtime version value. It preserves the original string without normalization or validation and does not require any particular versioning scheme.

func (Version) String

func (v Version) String() string

String returns the implementation-provided version string unchanged.

Directories

Path Synopsis
Package debugger defines portable contracts and values for controlling and inspecting Ferret debug sessions, including events, breakpoints, frames, and values.
Package debugger defines portable contracts and values for controlling and inspecting Ferret debug sessions, including events, breakpoints, frames, and values.
Package diagnostics defines the portable structured reporting model shared by Ferret runtimes and tooling.
Package diagnostics defines the portable structured reporting model shared by Ferret runtimes and tooling.
Package result defines consumable encoded Output handles and detached Content.
Package result defines consumable encoded Output handles and detached Content.
Package source defines portable Ferret source inputs and coordinates.
Package source defines portable Ferret source inputs and coordinates.

Jump to

Keyboard shortcuts

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