18#ifndef A11_ACTIONS_ACTION_H_
19#define A11_ACTIONS_ACTION_H_
29#include <absl/base/thread_annotations.h>
30#include <absl/container/flat_hash_map.h>
31#include <absl/container/flat_hash_set.h>
32#include <absl/status/status.h>
33#include <absl/status/statusor.h>
34#include <absl/time/time.h>
40#include "thread/boost_primitives.h"
87 static absl::StatusOr<std::shared_ptr<ActionLimiter>>
Create(
size_t maximum);
97 const size_t maximum_;
98 size_t active_ ABSL_GUARDED_BY(mu_) = 0;
99 std::shared_ptr<thread::PermanentEvent> changed_ ABSL_GUARDED_BY(mu_);
112class Action :
public std::enable_shared_from_this<Action> {
126 static absl::StatusOr<std::shared_ptr<Action>>
Create(
129 std::shared_ptr<nodes::NodeMap> node_map =
nullptr,
130 std::shared_ptr<net::WireStream> stream =
nullptr,
131 std::shared_ptr<service::Session> session =
nullptr,
132 std::shared_ptr<ActionRegistry> registry =
nullptr,
133 size_t max_concurrent_nested_actions =
137 static absl::StatusOr<std::string>
MakeNodeId(std::string_view action_id,
138 std::string_view node_name);
141 [[nodiscard]] std::string
GetId()
const;
143 absl::Status
SetId(std::string action_id);
169 absl::Status
BindNodeMap(std::shared_ptr<nodes::NodeMap> node_map);
171 [[nodiscard]] std::shared_ptr<nodes::NodeMap>
GetNodeMap()
const;
173 absl::Status
BindStream(std::shared_ptr<net::WireStream> stream);
175 [[nodiscard]] std::shared_ptr<net::WireStream>
GetStream()
const;
177 absl::Status
BindRegistry(std::shared_ptr<ActionRegistry> registry);
179 [[nodiscard]] std::shared_ptr<ActionRegistry>
GetRegistry()
const;
181 absl::Status
BindSession(std::shared_ptr<service::Session> session);
183 [[nodiscard]] std::shared_ptr<service::Session>
GetSession()
const;
186 absl::StatusOr<std::shared_ptr<nodes::AsyncNode>>
GetNode(
187 std::string node_id);
194 absl::StatusOr<std::shared_ptr<nodes::AsyncNode>>
GetInput(
195 std::string name, std::optional<bool> bind_stream = std::nullopt);
202 absl::StatusOr<std::shared_ptr<nodes::AsyncNode>>
GetOutput(
203 std::string name, std::optional<bool> bind_stream = std::nullopt);
205 absl::StatusOr<std::shared_ptr<nodes::AsyncNode>>
GetPort(std::string name);
207 [[nodiscard]]
bool ContainsPort(std::string_view name)
const;
217 absl::StatusOr<std::optional<data::Bytes>>
GetHeader(
218 std::string_view name)
const;
220 [[nodiscard]]
bool HasHeader(std::string_view name)
const;
226 absl::Status
ForwardHeader(
const std::shared_ptr<Action>& target,
227 std::string_view name)
const;
230 const std::shared_ptr<Action>& target,
246 absl::StatusOr<std::shared_ptr<Action>>
MakeNested(
248 bool forward_headers =
true);
260 absl::StatusOr<std::shared_ptr<Action>>
MakeNested(
261 std::string_view action_name,
bool propagate_io =
true,
262 bool forward_headers =
true);
273 absl::StatusOr<std::shared_ptr<Action>>
Run();
286 absl::Duration timeout = absl::InfiniteDuration());
294 absl::Duration timeout = absl::InfiniteDuration());
306 [[nodiscard]] std::string
TraceId()
const;
308 [[nodiscard]] std::string
SpanId()
const;
335 [[nodiscard]]
bool IsDone()
const;
343 [[nodiscard]] absl::Status
GetStatus()
const;
348 enum class Mode { kNone, kRun, kCall, kCancelled };
351 std::shared_ptr<nodes::NodeMap> node_map,
352 std::shared_ptr<net::WireStream> stream,
353 std::shared_ptr<service::Session> session,
354 std::shared_ptr<ActionRegistry> registry,
355 std::shared_ptr<ActionLimiter> nested_limiter);
357 absl::Status Begin(Mode mode);
358 absl::Status RemapDefaultPorts() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
359 absl::Status AttachStreamIfRequested(
360 const std::shared_ptr<nodes::AsyncNode>& node,
bool bind);
361 absl::Status ValidateMessagePorts(
362 const std::vector<data::Port>& ports,
363 const absl::flat_hash_map<std::string, ActionPortSchema>& schema_ports,
364 std::string_view kind)
const;
365 void RunHandler(std::shared_ptr<ActionLimiter> limiter);
366 absl::Status ApplyInputAutofills();
367 [[nodiscard]] std::vector<data::NodeFragment> CollectAutofillFragments()
369 void StartFinish(absl::Status status);
370 absl::Status FinishRun(absl::Status status);
371 absl::Status FinishOutputNodes(
const absl::Status& status);
372 absl::Status CommunicateStatus(
const absl::Status& status);
373 absl::Status AbortInputs(
const absl::Status& status);
374 absl::Status SendNodeAbortStatuses(
375 const absl::flat_hash_set<std::string>& node_ids,
376 const absl::Status& status);
377 absl::Status ReleaseNodesAfterRun();
378 absl::Status DetachBoundStreamNodes();
379 absl::Status SendRemoteCancel();
380 void CompleteCall(absl::Status status,
bool remove_from_session);
381 void AbortLocalCallOutputs(absl::Status status);
382 absl::Status TrackInSession(
const std::shared_ptr<service::Session>& session);
383 void UntrackFromSession();
384 void SetDispatchStatus(absl::Status status);
385 void SetCompletionStatus(absl::Status status);
392 absl::Status StartActionSpan(Mode mode);
393 void EndActionSpan(
const absl::Status& status);
395 void RecordActionCallEvent(std::string_view name, std::string_view
id);
397 mutable thread::Mutex mu_;
400 std::string id_ ABSL_GUARDED_BY(mu_);
403 std::shared_ptr<nodes::NodeMap> node_map_ ABSL_GUARDED_BY(mu_);
404 std::shared_ptr<net::WireStream> stream_ ABSL_GUARDED_BY(mu_);
405 std::weak_ptr<service::Session> session_ ABSL_GUARDED_BY(mu_);
406 std::weak_ptr<service::Session> tracked_session_ ABSL_GUARDED_BY(mu_);
407 std::shared_ptr<ActionRegistry> registry_ ABSL_GUARDED_BY(mu_);
408 absl::flat_hash_map<std::string, std::string> input_ids_ ABSL_GUARDED_BY(mu_);
409 absl::flat_hash_map<std::string, std::string> output_ids_
410 ABSL_GUARDED_BY(mu_);
411 absl::flat_hash_set<std::shared_ptr<nodes::AsyncNode>> input_nodes_
412 ABSL_GUARDED_BY(mu_);
413 absl::flat_hash_set<std::shared_ptr<nodes::AsyncNode>> output_nodes_
414 ABSL_GUARDED_BY(mu_);
415 absl::flat_hash_set<std::shared_ptr<nodes::AsyncNode>> stream_bound_nodes_
416 ABSL_GUARDED_BY(mu_);
417 Mode mode_ ABSL_GUARDED_BY(mu_) = Mode::kNone;
418 bool input_autofills_applied_ ABSL_GUARDED_BY(mu_) =
false;
421 bool span_status_set_by_user_ ABSL_GUARDED_BY(mu_) =
false;
422 bool cancel_requested_ ABSL_GUARDED_BY(mu_) =
false;
423 bool finishing_ ABSL_GUARDED_BY(mu_) =
false;
424 std::optional<absl::Status> completion_status_ ABSL_GUARDED_BY(mu_);
425 std::optional<absl::Status> dispatch_status_ ABSL_GUARDED_BY(mu_);
426 std::shared_ptr<a11::Promise<a11::Unit>> done_promise_ ABSL_GUARDED_BY(mu_);
427 a11::Task done_future_ ABSL_GUARDED_BY(mu_);
428 std::shared_ptr<a11::Promise<a11::Unit>> dispatch_promise_
429 ABSL_GUARDED_BY(mu_);
430 a11::Task dispatch_future_ ABSL_GUARDED_BY(mu_);
431 std::vector<OnActionCancelled> cancel_callbacks_ ABSL_GUARDED_BY(mu_);
432 std::weak_ptr<Action> parent_ ABSL_GUARDED_BY(mu_);
433 absl::flat_hash_set<std::shared_ptr<Action>> children_ ABSL_GUARDED_BY(mu_);
434 std::shared_ptr<ActionLimiter> nested_limiter_ ABSL_GUARDED_BY(mu_);
Shared handle to one asynchronous result.
Definition future.h:110
Cancellation-aware counting semaphore for nested-action concurrency.
Definition action.h:84
absl::Status Acquire()
Acquires a slot, blocking until one is free or cancelled.
Definition action.cc:119
void Release()
Releases a previously acquired slot.
Definition action.cc:139
static absl::StatusOr< std::shared_ptr< ActionLimiter > > Create(size_t maximum)
Creates a limiter admitting at most maximum holders.
Definition action.cc:105
A thread-safe catalogue mapping action names to schema and handler.
Definition registry.h:43
A11's unit of work: a schema-described, asynchronously run operation.
Definition action.h:112
absl::Status ClearInputsAfterRun(bool clear=true)
Sets whether inputs are released after each run.
Definition action.cc:331
void SetSpanStatus(obs::SpanStatus status, std::string_view description={})
Sets the span status explicitly.
Definition action.cc:1093
absl::StatusOr< std::shared_ptr< nodes::AsyncNode > > GetInput(std::string name, std::optional< bool > bind_stream=std::nullopt)
Returns the input port node named name.
Definition action.cc:447
absl::Status BindStream(std::shared_ptr< net::WireStream > stream)
Binds the wire stream used to dispatch the action remotely.
Definition action.cc:354
std::optional< absl::Status > GetDispatchStatus() const
The remote dispatch status, or nullopt when not (yet) dispatched.
Definition action.cc:973
bool HasBeenRun() const
Whether the action has been started with Run.
Definition action.cc:951
absl::Status SetId(std::string action_id)
Sets this action's instance id.
Definition action.cc:250
absl::Status BindSession(std::shared_ptr< service::Session > session)
Binds the owning session.
Definition action.cc:406
absl::StatusOr< std::optional< data::Bytes > > GetHeader(std::string_view name) const
Returns header name, or nullopt when absent.
Definition action.cc:581
data::ByteMap Headers() const
Returns a copy of all headers.
Definition action.cc:576
absl::Status SetOnCancelled(OnActionCancelled callback)
Registers a callback invoked when the action is cancelled.
Definition action.cc:938
std::string GetId() const
Returns this action's instance id.
Definition action.cc:245
absl::Status RemoveHeader(std::string_view name)
Removes header name.
Definition action.cc:610
std::string TraceId() const
This action's trace id as lowercase hex.
Definition action.cc:1058
bool HasBeenCalled() const
Whether the action has been dispatched with Call.
Definition action.cc:956
ActionSchema GetSchema() const
Returns this action's schema.
Definition action.cc:268
std::shared_ptr< nodes::NodeMap > GetNodeMap() const
Returns the bound node map.
Definition action.cc:349
std::shared_ptr< service::Session > GetSession() const
Returns the owning session, if any.
Definition action.cc:429
ActionSettings GetSettings() const
Returns the action's current settings.
Definition action.cc:308
void SetSpanName(std::string_view name)
Overrides the display name of this action's span.
Definition action.cc:1088
absl::Status SetSchema(ActionSchema schema)
Replaces this action's schema (validated).
Definition action.cc:273
bool ContainsPort(std::string_view name) const
Whether the schema declares a port named name.
Definition action.cc:531
absl::Status ForwardHeadersWithPrefix(const std::shared_ptr< Action > &target, std::string_view prefix=kActionHeaderPrefix) const
Copies all headers starting with prefix onto target.
Definition action.cc:631
absl::Status ClearOutputsAfterRun(bool clear=true)
Sets whether outputs are released after each run.
Definition action.cc:337
absl::Status BindRegistry(std::shared_ptr< ActionRegistry > registry)
Binds the registry used to resolve nested actions by name.
Definition action.cc:395
static absl::StatusOr< std::shared_ptr< Action > > Create(ActionSchema schema, std::string action_id={}, ActionHandler handler={}, std::shared_ptr< nodes::NodeMap > node_map=nullptr, std::shared_ptr< net::WireStream > stream=nullptr, std::shared_ptr< service::Session > session=nullptr, std::shared_ptr< ActionRegistry > registry=nullptr, size_t max_concurrent_nested_actions=kDefaultMaxConcurrentNestedActions)
Creates an action.
Definition action.cc:152
absl::StatusOr< std::shared_ptr< nodes::AsyncNode > > GetPort(std::string name)
Returns the input or output port node named name.
Definition action.cc:511
absl::Status MapPortsFromMessage(const data::ActionMessage &message)
Binds this action's ports to the nodes named in message.
Definition action.cc:554
absl::Status BindStreamsOnInputsByDefault(bool bind)
Sets whether input port streams are bound by default.
Definition action.cc:319
bool Cancelled() const
Whether cancellation has been requested/applied.
Definition action.cc:961
a11::Future< std::shared_ptr< Action > > Wait(absl::Duration timeout=absl::InfiniteDuration())
Awaits completion of the action.
Definition action.cc:857
a11::Future< std::shared_ptr< Action > > Call(data::ByteMap wire_headers={})
Dispatches the action to a peer over the bound wire stream.
Definition action.cc:759
absl::Status GetStatus() const
The action's completion status (OK while still running).
Definition action.cc:968
absl::Status SetHeader(std::string name, data::Bytes value)
Sets header name to value.
Definition action.cc:601
absl::Status BindNodeMap(std::shared_ptr< nodes::NodeMap > node_map)
Binds the node map that backs this action's ports.
Definition action.cc:343
absl::Status BindHandler(ActionHandler handler)
Binds the handler invoked when the action runs.
Definition action.cc:286
data::ActionMessage GetActionMessage() const
Returns the wire a11::data::ActionMessage describing this action.
Definition action.cc:537
absl::StatusOr< std::shared_ptr< nodes::AsyncNode > > GetOutput(std::string name, std::optional< bool > bind_stream=std::nullopt)
Returns the output port node named name.
Definition action.cc:479
std::string SpanId() const
This action's span id as lowercase hex, or empty when untraced.
Definition action.cc:1063
absl::Status Cancel()
Requests cancellation of the action (local or remote).
Definition action.cc:883
bool HasHandler() const
Whether a handler is bound.
Definition action.cc:303
bool IsDone() const
Whether the action has finished (successfully or not).
Definition action.cc:946
std::shared_ptr< ActionRegistry > GetRegistry() const
Returns the bound registry.
Definition action.cc:401
bool HasHeader(std::string_view name) const
Whether header name is set.
Definition action.cc:594
void SetSpanAttribute(std::string_view key, std::string_view value)
Sets a string attribute on this action's span.
Definition action.cc:1068
a11::Future< absl::Status > WaitForDispatch(absl::Duration timeout=absl::InfiniteDuration())
Awaits acceptance of a remote dispatch.
Definition action.cc:813
static absl::StatusOr< std::string > MakeNodeId(std::string_view action_id, std::string_view node_name)
Derives the node id for port node_name of action action_id.
Definition action.cc:230
absl::Status BindStreamsOnOutputsByDefault(bool bind)
Sets whether output port streams are bound by default.
Definition action.cc:325
absl::StatusOr< std::shared_ptr< Action > > Run()
Runs the action's handler locally.
Definition action.cc:709
std::shared_ptr< net::WireStream > GetStream() const
Returns the bound wire stream.
Definition action.cc:390
absl::StatusOr< std::shared_ptr< nodes::AsyncNode > > GetNode(std::string node_id)
Returns the port node with raw id node_id.
Definition action.cc:434
absl::Status ForwardHeader(const std::shared_ptr< Action > &target, std::string_view name) const
Copies header name from this action onto target.
Definition action.cc:619
absl::Status SetSettings(ActionSettings settings)
Replaces the action's settings.
Definition action.cc:313
ActionHandler GetHandler() const
Returns the currently bound handler.
Definition action.cc:298
absl::StatusOr< std::shared_ptr< Action > > MakeNested(const ActionSchema &schema, bool propagate_io=true, bool forward_headers=true)
Creates a nested action from a schema, parented to this action.
Definition action.cc:647
A bidirectional, message-oriented channel between two A11 endpoints.
Definition wire_stream.h:89
An asynchronous, ordered stream of chunks read from and written to A11.
Definition async_node.h:70
A thread-safe registry of AsyncNodes keyed by id.
Definition node_map.h:51
Move-only RAII handle to one action, session, or transport span.
Definition span.h:37
A connection-scoped runtime that multiplexes wire streams and runs actions.
Definition session.h:112
Completion values used by every asynchronous A11 operation.
ActionHandler MakeAsyncActionHandler(SyncActionHandler handler)
Adapts a synchronous handler into an asynchronous ActionHandler.
Definition action.cc:89
std::function< absl::Status(std::shared_ptr< Action >)> SyncActionHandler
Synchronous action handler returning a completion status.
Definition action.h:70
constexpr std::string_view kActionHeaderPrefix
Prefix reserved for A11's framework headers.
Definition schema.h:47
constexpr size_t kDefaultMaxConcurrentNestedActions
Default cap on concurrently running nested actions.
Definition action.h:65
std::function< absl::Status(std::shared_ptr< Action >)> OnActionCancelled
Callback invoked when an action is cancelled.
Definition action.h:72
std::function< a11::Task(std::shared_ptr< Action >)> ActionHandler
Asynchronous action handler: runs the action, returns an awaitable.
Definition action.h:68
std::string Bytes
Raw byte payload; an alias of std::string.
Definition types.h:40
absl::flat_hash_map< std::string, Bytes > ByteMap
String-keyed map of byte values (headers, attributes, etc.).
Definition types.h:42
SpanStatus
OpenTelemetry outcome states, mirrored to keep OTel out of this API.
Definition span.h:24
SpanKind
OpenTelemetry span relationships, mirrored to keep OTel out of this API.
Definition span.h:21
Future< Unit > Task
Asynchronous operation whose only successful result is completion itself.
Definition future.h:403
Schemas describing an action's typed interface and its settings.
The full typed interface of an action.
Definition schema.h:107
Per-action runtime settings for stream binding and cleanup.
Definition schema.h:139
The wire description of an action invocation.
Definition types.h:239
A11's core wire value types: chunks, node fragments and messages.