Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@ Implementations own engine configuration; consumers share `Runtime`, reusable
`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.
`Params() ([]string, error)` returns a caller-owned snapshot or a metadata
retrieval error. It does not take a context.
`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
Expand Down Expand Up @@ -58,7 +71,8 @@ The output fields and their serialized representation are unchanged. Transports
preserve output presence through their own representations.

Non-nil caller contexts control cancellation of `Run`, `Compile`,
`CompileDebug`, `NewSession`, and `NewDebugSession`. Cancellation errors
`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`.
Implementations need not derive operation contexts to coordinate parent Close.
They may use internal contexts for their own resources and may translate portable
Expand Down
10 changes: 10 additions & 0 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
// Package api defines implementation-independent contracts for compiling,
// executing, and debugging Ferret queries.
//
// 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.
package api
4 changes: 4 additions & 0 deletions output_contract_fixture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ var (
_ api.Session = (*outputSession)(nil)
)

func (r *outputRuntime) Version(context.Context) (api.Version, error) {
return api.Version(""), nil
}

func (r *outputRuntime) Run(context.Context, api.Source, ...api.SessionOption) (*api.Output, error) {
return r.output, r.err
}
Expand Down
14 changes: 11 additions & 3 deletions plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,28 @@ import (
type (
// Plan represents a compiled program. Compilation finishes before a plan is
// returned. Plans support independent sessions and are not consumed by execution.
// Params returns a caller-owned snapshot or an error if metadata cannot be retrieved.
//
// 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.
//
// NewSession and NewDebugSession use non-nil caller contexts for cancellation.
// 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.
Plan interface {
io.Closer
Params() ([]string, error)

// 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)
}
Expand Down
10 changes: 7 additions & 3 deletions plan_contract_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package api_test

import "github.com/MontFerret/api"
import (
"context"

// Metadata retrieval can fail without adding a context to Plan.Params.
var _ func(api.Plan) ([]string, error) = api.Plan.Params
"github.com/MontFerret/api"
)

// Parameter metadata retrieval is fallible and context-aware.
var _ func(api.Plan, context.Context) ([]string, error) = api.Plan.Params
13 changes: 12 additions & 1 deletion runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,23 @@ import (
// adapter and underlying runtime usable. Close does not implicitly cancel
// caller-owned work and need not wait for operations already started.
//
// Run, Compile, and CompileDebug use non-nil caller contexts for cancellation.
// Run, Compile, CompileDebug, and Version use non-nil caller contexts for cancellation.
// Callers coordinate work and cleanup when descendants use parent-owned
// resources. Run closes its temporary session and plan, preserving execution
// and cleanup errors together with any available encoded output.
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 returns nil output with an error when no output was produced.
// A non-nil output with a nil error indicates success, including empty output.
// A non-nil output may accompany an error from cleanup or other processing;
Expand Down
10 changes: 10 additions & 0 deletions runtime_contract_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package api_test

import (
"context"

"github.com/MontFerret/api"
)

// Runtime version retrieval is fallible and context-aware.
var _ func(api.Runtime, context.Context) (api.Version, error) = api.Runtime.Version
11 changes: 11 additions & 0 deletions version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package api

// 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.
type Version string

// String returns the implementation-provided version string unchanged.
func (v Version) String() string {
return string(v)
}
27 changes: 27 additions & 0 deletions version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package api_test

import (
"testing"

"github.com/MontFerret/api"
)

func TestVersionStringPreservesValue(t *testing.T) {
for _, tc := range []struct {
name string
value string
}{
{name: "empty", value: ""},
{name: "prerelease", value: "v2.0.0-alpha.55"},
{name: "release", value: "2.0.0"},
{name: "development", value: "dev"},
{name: "unknown", value: "unknown"},
{name: "opaque with whitespace", value: " \tbuild:abc123+custom\n "},
} {
t.Run(tc.name, func(t *testing.T) {
if got := api.Version(tc.value).String(); got != tc.value {
t.Fatalf("Version.String() = %q, want %q", got, tc.value)
}
})
}
}
Loading