ข้ามไปยังเนื้อหา

Cephalon.Data.OpenSearch

เนื้อหานี้ยังไม่ได้แปลเป็นภาษาไทย แสดงเป็นภาษาอังกฤษแทน

Maturity: M1 · Ownership: provider-managed · Family: data-and-cdc · See audit, matrix.

Cephalon.Data.OpenSearch is the OpenSearch search-store companion pack for Cephalon, mirroring the pattern established by Cephalon.Data.Elasticsearch against the OpenSearch.Client 1.9.0 API surface.

  • registers a singleton OpenSearchClient (from OpenSearch.Client 1.9.0) using TryAdd semantics so a host-owned client is never displaced
  • optionally configures Basic authentication via ConnectionSettings.BasicAuthentication(...) when Username is set
  • registers a scoped IOutbox backed by an OpenSearch index when RegisterOutbox is enabled; documents are staged with OpType.Create for idempotency — HTTP 409 (ServerError.Status == 409) is swallowed silently
  • registers a scoped IEventDispatchStore over that same outbox index when RegisterOutbox is enabled, so staged OpenSearch events can be read and durable dispatch outcomes can be written back through the runtime-neutral eventing contract
  • registers a scoped IInbox backed by a separate OpenSearch index when RegisterInbox is enabled; existence is checked via GetAsync by document id; marking uses OpType.Create with 409 swallow
  • exposes operator-facing outbox and inbox descriptors through the engine runtime surfaces
  • projects outbox and inbox descriptors through the event-driven-integration technology surface when that technology is active
  • publishes capability metadata data.opensearch, data.search-store, and optionally data.outbox.opensearch and data.inbox.opensearch introspectable at runtime through the manifest
  • Configuration/OpenSearchDataOptions.cs
  • Modules/OpenSearchDataModule.cs
  • Registration/OpenSearchDataEngineBuilderExtensions.cs
  • Services/OpenSearchOutbox.cs
  • Services/OpenSearchEventDispatchStore.cs
  • Services/OpenSearchOutboxRuntimeSurfaceContributor.cs
  • Services/OpenSearchInbox.cs
  • Services/OpenSearchInboxRuntimeSurfaceContributor.cs

This pack sits on top of Cephalon.Data, not in place of it. Cephalon.Data.OpenSearch adds OpenSearch-backed outbox and inbox persistence paths that let event-driven workloads stage and track messages against a search index. It is a drop-in sibling to Cephalon.Data.Elasticsearch for teams running OpenSearch clusters, and it now also exposes the same staged outbox through IEventDispatchStore so consumer-managed or adapter-owned dispatch loops can read pending items and persist durable dispatch outcomes without OpenSearch-specific host glue.

engine.AddOpenSearchData("http://localhost:9200");

To enable outbox and inbox paths:

engine.AddOpenSearchData("http://localhost:9200", options =>
{
options.RegisterOutbox = true;
options.RegisterInbox = true;
options.IndexPrefix = "myapp-"; // optional — prefix all Cephalon-managed index names
});

With Basic authentication:

engine.AddOpenSearchData("https://my-cluster.opensearch.example.com:9200", options =>
{
options.Username = "admin";
options.Password = "secret";
options.RegisterOutbox = true;
});

To resolve the node URI from the root Uris section:

engine.AddOpenSearchData(options =>
{
options.UriName = "SearchCluster";
options.Username = "admin";
options.Password = "secret";
options.RegisterOutbox = true;
});
{
"Uris": {
"SearchCluster": "https://my-cluster.opensearch.example.com:9200"
},
"Engine": {
"Data": {
"OpenSearch": {
"UriName": "SearchCluster",
"IndexPrefix": "myapp-"
}
}
}
}

UriName and Uri are mutually exclusive. If both are set, the pack throws during service registration. Leaving both unset falls back to http://localhost:9200.

OptionTypeDefaultDescription
UriNamestring?nullRoot Uris key to resolve for OpenSearch
Uristring?nullInline OpenSearch node URI
Usernamestring?nullOptional username for Basic authentication
Passwordstring?nullOptional password for Basic authentication
IndexPrefixstring""Prefix applied to all Cephalon-managed index names
RegisterOutboxboolfalseRegister IOutbox backed by {IndexPrefix}outbox-messages
RegisterInboxboolfalseRegister IInbox backed by {IndexPrefix}inbox-receipts

Outbox document schema ({IndexPrefix}outbox-messages)

Section titled “Outbox document schema ({IndexPrefix}outbox-messages)”
FieldJSON nameTypeNotes
MessageIdmessage_idstringDocument _id; idempotency key via OpType.Create
ChannelIdchannel_idstringTarget channel identifier
MessageTypemessage_typestringFully qualified CLR message type name
PayloadpayloadstringSystem.Text.Json-serialized message body
ContentTypecontent_typestringMIME content type
CorrelationIdcorrelation_idstring?Optional causality tracking identifier
TenantIdtenant_idstring?Optional multi-tenancy discriminator
OccurredAtUtcoccurred_at_utcDateTimeWhen the domain event occurred
CreatedAtUtccreated_at_utcDateTimeWhen the message was staged
DispatchAttemptCountdispatch_attempt_countintInitialized to 0
HeadersJsonheaders_jsonstringSystem.Text.Json-serialized headers dictionary
MetadataJsonmetadata_jsonstringSystem.Text.Json-serialized metadata dictionary

Inbox document schema ({IndexPrefix}inbox-receipts)

Section titled “Inbox document schema ({IndexPrefix}inbox-receipts)”
FieldJSON nameTypeNotes
MessageIdmessage_idstringDocument _id; idempotency key
ChannelIdchannel_idstringChannel the message arrived on
MessageTypemessage_typestringFully qualified CLR message type name
ReceivedAtUtcreceived_at_utcDateTimeWhen the message was received
ProcessedAtUtcprocessed_at_utcDateTimeWhen the message was first processed
CorrelationIdcorrelation_idstring?Optional causality tracking identifier
TenantIdtenant_idstring?Optional multi-tenancy discriminator

Both IOutbox.EnqueueAsync and IInbox.MarkProcessedAsync use OpType.Create when indexing documents:

  • HTTP 409 (response.ServerError?.Status == 409) is swallowed silently — making repeated calls with the same message id safe no-ops
  • Any other non-success response (!response.IsValid) is a real error and throws InvalidOperationException

IInbox.HasProcessedAsync uses GetAsync by document id — response.IsValid && response.Found determines whether the message has been processed.

When OpenSearchDataModule is active, the following capability keys appear in the runtime manifest:

Capability keyWhen registered
data.opensearchAlways
data.search-storeAlways
data.outbox.opensearchRegisterOutbox = true
data.inbox.opensearchRegisterInbox = true

The companion event-store pack is Cephalon.EventSourcing.OpenSearch. It registers IEventStore with compound document ids {streamId}#{streamVersion} for uniqueness and application-layer optimistic concurrency.

builder.Services.AddCephalonOpenSearchEventSourcing(
uri: "http://localhost:9200",
indexName: "event-streams");

This pack intentionally does not claim:

  • full-text search, aggregations, or IReadStore / IWriteStore dispatch backed by OpenSearch
  • index lifecycle management or template provisioning
  • cross-cluster search or multi-index querying
  • pack-owned dispatch loops or broker-specific retry scheduling beyond the runtime-neutral IEventDispatchStore bridge
  • bulk indexing or pipeline ingestion