-
Notifications
You must be signed in to change notification settings - Fork 0
#71: Document v2 runner architecture #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
db61309
protocol: add v2 protocol design
tkilias 12e29d2
protocol: add run batch correlation
tkilias 695d2b1
protocol: mark completed run groups
tkilias 95841aa
protocol: define high-level payload contracts
tkilias 486798b
protocol: remove legacy metadata fields
tkilias 35c21be
Use Draft-07 v2 JSON schemas
tkilias 90b51c4
Reorganize v2 protocol design docs
tkilias ab08878
docs(v2): define high-level Exasol-to-Arrow type mapping
tkilias a4822d6
docs(v2): expose Exasol column type parameters
tkilias d615498
docs(v2): name Exasol type enum
tkilias a53378c
docs(v2): centralize schemas and examples with CI validation
tkilias ffedcd5
Merge origin/main into documentation/design_v2_protocol
tkilias cf85adb
docs(v2): map decimals to sized Arrow types
tkilias f458fb1
docs(v2): streamline type mapping metadata
tkilias 834ff7f
docs: consolidate v2 data stream references
tkilias 5a08777
docs: place call lifecycle under low-level protocol
tkilias b83f88f
docs: consolidate low-level data stream references
tkilias 2742461
some cleanup
tkilias 158f8c1
docs: use fixed-width year-month interval storage
tkilias a584dfa
sort files into sub directories
tkilias 9368b05
docs: address v2 protocol review comments
tkilias 8ee11b9
Add Arrow schema types and variadic buffers
tkilias c6290ed
Document v2 runner architecture diagrams
tkilias c666982
docs: replace runner ABI design with namespaces
tkilias 19178e8
docs: make runner the composition root
tkilias d27711d
docs: define worker-facing context interface
tkilias 6ae18fa
docs: model open call as first call message
tkilias 3ec8c8b
docs: add outbound call interface
tkilias d85d726
docs: add Arrow schema correlation flags
tkilias 8d4c98a
docs: add record batch group-end metadata
tkilias 729447a
docs: add specialized message builders and views
tkilias 170308a
docs: detail context background event loop
tkilias 73cfa4e
docs: address runner design review comments
tkilias b54dd71
docs: clarify split group boundaries
tkilias 0ced8c5
docs: hide batch splitting from context interface
tkilias 2e61fda
docs: refine context flow control design
tkilias ae63b1d
docs: define 4 MiB record batch splitting
tkilias 82ec289
Merge origin/main into architecture design
tkilias d8a0d2d
ci: remove JSON schema workflow
tkilias 466a63a
Delete udf-runner-cpp/v2/json_schema/validate_schemas.py
tkilias dd18feb
docs: prepare runner architecture PR
tkilias File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # UDF Runner v2 Design | ||
|
|
||
| This directory describes the runner-side architecture for protocol v2. It is a design document set; it does not | ||
| define an implementation or commit to a concrete C++ class layout. | ||
|
|
||
| The runner is organized into two source-level namespaces: | ||
|
|
||
| 1. The API namespace contains the caller-facing C++ contracts. | ||
| 2. The Internal namespace owns sockets, accepting, worker scheduling, protocol contexts, and implementation | ||
| dependencies. | ||
|
|
||
| `Runner` is the composition root for those components. A runner user transfers a `WorkerFactory` to a production | ||
| factory, which constructs `Runner` and its remaining owned components. Unit tests use the same construction seam with | ||
| owned test doubles. | ||
|
|
||
| The API namespace must not expose third-party symbols from the Internal namespace. A dependency may cross this | ||
| boundary only when it is vendored into an owned project namespace or uses a well-known interoperable ABI, such as the | ||
| Arrow C Data Interface. | ||
|
|
||
| ## Documents | ||
|
|
||
| - [architecture.md](architecture.md) defines the namespace boundary and component responsibilities. | ||
| - [lifecycle.md](lifecycle.md) defines connection, worker, context, and shutdown lifecycles. | ||
| - [context_interface.md](context_interface.md) defines the worker-facing low-level context, call, and control-stream | ||
| contract. | ||
| - [context_implementation.md](context_implementation.md) defines the internal queues, background I/O thread, | ||
| notification, batching, and shutdown design. | ||
|
|
||
| Mermaid `.mmd` files are the diagram sources of truth. Matching `.svg` files are rendered views linked from the | ||
| documents. | ||
|
|
||
| ## Relationship to the protocol | ||
|
|
||
| The runner implements the protocol described in the [v2 protocol design](../README.md). In particular: | ||
|
|
||
| - [protocol.md](../protocol/low_level/protocol.md) defines framing, streams, transport bindings, and close behavior. | ||
| - [call_lifecycle.md](../protocol/low_level/call_lifecycle.md) defines the generic call abstraction. | ||
| - [calls.md](../protocol/high_level/calls.md) defines `Run`, Function operations, and callbacks. | ||
| - [payloads.md](../protocol/high_level/payloads.md) defines JSON and named payload contracts. | ||
|
|
||
| The runner `Context` is the implementation boundary for those protocol rules. This design does not redefine their | ||
| wire format. | ||
|
|
||
| ## Initial transport | ||
|
|
||
| The first concrete transport is a Unix-domain stream socket. The socket and acceptor contracts are intentionally | ||
| transport-neutral enough to support a future TCP/TLS binding without changing the protocol context contract. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| # Runner v2 Architecture | ||
|
|
||
| ## Layering | ||
|
|
||
| ```text | ||
| API namespace: caller-facing C++ contracts | ||
| | | ||
| v | ||
| Internal namespace: sockets, acceptor, worker pool, factory, context manager, context | ||
| | | ||
| v | ||
| Protocol v2 | ||
| ``` | ||
|
|
||
| Related diagrams: | ||
|
|
||
| - [layered_architecture.svg](layered_architecture.svg) | ||
| - [component_relationships.svg](component_relationships.svg) | ||
|
|
||
| Dependencies point downward only. The API namespace contains only project-owned caller-facing contracts. The Internal | ||
| namespace may use C++ standard-library types, exceptions, and third-party libraries such as Arrow C++. | ||
|
|
||
| Third-party symbols must not leak from the Internal namespace through the API namespace. A dependency is allowed at | ||
| the API boundary only when it is vendored into an owned project namespace or communicated through a well-known ABI. | ||
| The current well-known ABI exception is the Arrow C Data Interface: `ArrowArray` and `ArrowSchema` may cross the | ||
| boundary under its release and ownership contract; Arrow C++ types remain internal. | ||
|
|
||
| ## Components | ||
|
|
||
| ### Runner | ||
|
|
||
| `Runner` is the composition root. A runner user transfers ownership of a `WorkerFactory` to a production factory. | ||
| The production factory constructs a `Runner` with that factory, transport configuration, limits, a `SocketAcceptor`, | ||
| a worker pool, and a `ContextManager`. `Runner` validates and connects those components, starts and stops them, and | ||
| destroys them in dependency-safe order after all work has completed. | ||
|
|
||
| Unit tests use the same construction seam to create a `Runner` with owned fakes, stubs, or instrumented component | ||
| implementations. The production factory is responsible only for choosing concrete production implementations; the | ||
| runner remains responsible for their configuration and composition. | ||
|
|
||
| ### Socket | ||
|
|
||
| `Socket` represents one connected byte stream. It owns the accepted descriptor and provides the operations required | ||
| by the protocol transport: receive bytes, send bytes, observe closure, and close. The initial implementation uses a | ||
| Unix-domain stream descriptor. The abstraction must not expose Unix-specific address types to the protocol context. | ||
|
|
||
| The socket owns its descriptor after construction. Closing or destroying the socket makes the descriptor unusable; | ||
| ownership must not be duplicated implicitly. | ||
|
|
||
| ### SocketAcceptor | ||
|
|
||
| `SocketAcceptor` owns the listening endpoint, performs bind/listen setup, and accepts connected sockets. It submits | ||
| each accepted descriptor to the worker scheduler. Accept failures are classified as retryable, shutdown-related, or | ||
| fatal and must not silently become worker failures. | ||
|
|
||
| The initial acceptor listens on a Unix-domain socket. The interface leaves endpoint configuration and accepted-socket | ||
| creation abstract so a TCP/TLS acceptor can be added later. | ||
|
|
||
| ### WorkerFactory and worker pool | ||
|
|
||
| The runner user initially owns `WorkerFactory` and transfers it to the production factory, which transfers ownership | ||
| to `Runner`. The factory is used by reusable worker-pool resources to obtain a worker callable or worker object for | ||
| an accepted descriptor. `Runner` destroys the factory only after stopping and joining all worker activity. | ||
|
|
||
| The pool is reusable, but a worker invocation handles one accepted connection. A worker must not retain a protocol | ||
| context or descriptor after its invocation returns. Pool sizing, queue limits, and shutdown policy are explicit runner | ||
| configuration rather than hidden global state. | ||
|
|
||
| ### Worker | ||
|
|
||
| A worker receives one accepted descriptor, asks the `ContextManager` to create a protocol context, runs that context | ||
| until normal close, peer disconnect, cancellation, or error, and then releases the context and descriptor. The worker | ||
| does not parse protocol messages outside the context boundary. | ||
|
|
||
| ### ContextManager | ||
|
|
||
| `ContextManager` converts an owned connected descriptor into a connection-scoped `Context`. It centralizes context | ||
| construction, protocol dependencies, limits, cancellation, and cleanup. Context creation failure must close or reclaim | ||
| the descriptor according to the documented ownership handoff. | ||
|
|
||
| ### Context | ||
|
|
||
| `Context` is the runner-side interface to protocol v2. It owns one connection and exposes the operations needed by the | ||
| protocol implementation: framing, control-stream initialization, stream dispatch, call/data handling, callbacks, | ||
| keepalive, and close/error processing. | ||
|
|
||
| The worker-facing contract for this component is defined in [context_interface.md](context_interface.md). The worker | ||
| uses connection-wide readiness and call acceptance, then receives call-scoped messages through a `Call` object or | ||
| connection-level messages through the stream-0 control interface. The contract permits composite call messages and | ||
| uses the Arrow C Data Interface for record batches; transport, framing, and dispatch remain internal. | ||
|
|
||
| The context is not an application callback object and is not shared between worker invocations. It is the sole owner | ||
| of protocol state for its connection and must enforce the validation, ordering, flow-control, and close rules from the | ||
| protocol documents. | ||
|
|
||
| ## Data and dependency flow | ||
|
|
||
| ```text | ||
| runner user --moves WorkerFactory--> production factory | ||
| | | ||
| v | ||
| Runner owns factory, acceptor, pool, and context manager | ||
| | | ||
| SocketAcceptor -> worker pool -> Worker(fd) -> ContextManager.create(fd) -> protocol Context | ||
| | | ||
| Socket bytes + Arrow C data values | ||
| ``` | ||
|
|
||
| Arrow record batches and schemas may cross the API boundary as `ArrowArray` and `ArrowSchema` under the Arrow C Data | ||
| Interface. Arrow C++ objects remain Internal-namespace implementation details and are released according to that | ||
| interface's ownership rules. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| flowchart LR | ||
| User[Runner user] -->|transfers WorkerFactory| Production[Production factory] | ||
| Production -->|constructs| Runner[Runner\ncomposition root] | ||
| Runner -->|owns| Factory[WorkerFactory] | ||
| Runner -->|owns| Acceptor[SocketAcceptor\nlistening endpoint] | ||
| Runner -->|owns| Queue[Reusable worker pool] | ||
| Runner -->|owns| Manager[ContextManager] | ||
| Acceptor -->|accepted fd| Queue | ||
| Factory -->|creates worker| Queue | ||
| Queue -->|one fd per invocation| Worker[Worker callable] | ||
| Worker -->|create context| Manager[ContextManager] | ||
| Manager -->|owns connection context| Context[Protocol Context] | ||
| Context --> Socket[Socket abstraction] | ||
| Socket --> Transport[Unix stream socket\nfuture TCP/TLS binding] | ||
| Context --> V2[Protocol v2 interface] |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| sequenceDiagram | ||
| participant User as Runner user | ||
| participant Production as Production factory | ||
| participant Runner | ||
| participant Acceptor as SocketAcceptor | ||
| participant Pool as Worker pool | ||
| participant Factory as WorkerFactory | ||
| participant Worker | ||
| participant Manager as ContextManager | ||
| participant Context | ||
|
|
||
| User->>Production: transfer WorkerFactory | ||
| Production->>Runner: construct with owned components | ||
| Runner->>Acceptor: configure and listen | ||
| Acceptor->>Acceptor: accept connection | ||
| Acceptor->>Pool: enqueue owned fd | ||
| Pool->>Factory: create worker for fd | ||
| Factory-->>Pool: worker callable | ||
| Pool->>Worker: invoke(fd) | ||
| Worker->>Manager: create_context(fd) | ||
| Manager-->>Worker: Context(connection) | ||
| Worker->>Context: run protocol v2 | ||
| Context-->>Context: close / disconnect / cancel / error | ||
| Context-->>Worker: return and release connection | ||
| Worker-->>Pool: invocation complete | ||
|
|
||
| alt queue, worker, or context creation failure | ||
| Acceptor-->>Acceptor: close fd exactly once | ||
| end |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.