# Explore the YDB walkthrough

Step through the YDB walkthrough, select a component, an object or a connection, and switch the scenario to see which step a changed fact changes.

Source: https://docs.ptah.run/edge/extend/write-a-provider/ydb-walkthrough-explore/

import YdbWalkthrough from '../../../../components/YdbWalkthrough.astro';

[Understanding the provider boundary](../ydb-walkthrough/) explains the
components and messages of one YDB example, and [What a comparison may
conclude](../ydb-incomplete-knowledge/) changes one fact of it at a time. The
figure puts both on one screen. Select a component, an object or a connection
to read about it, step through the workflow, and switch the scenario to see
which step its changed fact changes.

The figure shows fixed facts from the walkthrough and from the tests behind
it. It connects to no database and installs nothing.

<YdbWalkthrough />

## The walkthrough as text

The tables below hold every fact the figure shows, for a reader without
JavaScript and for the page's Markdown copy.

{/* Generated by scripts/build-ydb-walkthrough.mjs from src/ydb-walkthrough.mjs. Do not edit by hand. */}

### Components

| Component | Responsible for | Understands | Does not own |
| --- | --- | --- | --- |
| Ptah Core (Host: the ptah binary) | Loads the declaration, compares common tables, routes provider models to their owners, orders the whole plan, prints and applies it. | Common tables, identities and coverage. A provider payload only as bytes. | What a transfer means, or whether its source will exist after the plan. |
| Contract and SDK (Boundary between Core and the provider) | Defines the messages and features both sides agree on. The SDK checks each request and answer against them. | Message shapes, identities, representations and coverage records. | YDB meaning: a well-formed request can still describe a plan YDB would refuse. |
| YDB provider (Provider: the ptah-plugin-ydb executable) | Reads the YDB catalog, compares the models it owns, proposes plan steps, renders and runs YQL. | YDB semantics: changefeeds, topics, transfers and what each one needs. | Common tables, the order of the whole plan, and migration history policy. |
| YDB server (The database) | Stores the tables, keeps the changefeed and its topic, and runs the transfer after Ptah exits. | YQL statements and its own catalog. | The declaration, the comparison and the plan. |

### Objects

| Object | In YDB | In Ptah | Compared by |
| --- | --- | --- | --- |
| `orders` | Row table shop/orders | A common table; its YDB settings are a row-table-properties facet | Ptah Core for the table; ydb-row-table-properties for the facet |
| `orders/feed` | Changefeed of orders, with its topic shop/orders/feed | One entry in the table-changefeeds facet of orders | ydb-row-table-properties |
| `ingest_orders` | Transfer shop/ingest_orders | A provider object of kind transfer | ydb-transfers |
| `orders_archive` | Row table shop/orders_archive | A common table | Ptah Core |

| Object | In the ydb-transfers request | Plan step |
| --- | --- | --- |
| `orders` | declaredRelations, as a declared table | CREATE TABLE `shop/orders` |
| `orders/feed` | declaredFacets, as a changefeed orders declares; currentContext, once a read finds it | ALTER TABLE `shop/orders` ADD CHANGEFEED `feed`, then ALTER TOPIC `shop/orders/feed` ADD CONSUMER `archiver` |
| `ingest_orders` | desired, as the declared transfer; current, once it exists | CREATE TRANSFER `shop/ingest_orders` FROM `shop/orders/feed` TO `shop/orders_archive` |
| `orders_archive` | declaredRelations, as a declared table | CREATE TABLE `shop/orders_archive` |

### Workflow steps

| Step | Who acts | What happens | Result in a normal creation |
| --- | --- | --- | --- |
| 1. Declaration | Ptah Core, Contract and SDK, YDB provider | Core loads schema.yaml. The provider decodes the YDB extensions, the changefeed and the transfer, and the SDK checks their values. | The declared tables in Core's common model, and normalized values of the changefeed set and the transfer. |
| 2. Selection | Ptah Core, Contract and SDK, YDB provider | Core starts the provider and asks what it serves. Both agree on features, such as models.current-context, and the provider opens a session. | A session on the database and the list of features both sides negotiated. |
| 3. Reading | Ptah Core, YDB provider, YDB server | The provider reads the selected directory, shop, and says what it established about each kind. | Nothing in shop, and coverage that says shop was read completely. |
| 4. Comparison | Ptah Core, Contract and SDK, YDB provider | Core compares the common tables and sends each owner a request. ydb-transfers receives the declared transfer with the facts it needs about other owners. | A request with both tables in declaredRelations and the changefeed in declaredFacets. |
| 5. Changes or refusal | YDB provider | Each owner returns changes or refuses one and says why. ydb-transfers checks the transfer's source and target first. | Two new tables from Core, a new changefeed from ydb-row-table-properties and a new transfer from ydb-transfers. |
| 6. Planning | Ptah Core, Contract and SDK, YDB provider | The provider turns its changes into steps and says which steps depend on which. Core checks them and orders the whole plan. | Four operations, the transfer last, after its changefeed and both tables. |
| 7. Review and execution | Ptah Core, YDB provider, YDB server | Core prints the plan. On apply, the provider renders YQL and runs it, and YDB starts the transfer. | The statements run, and a row written to orders reaches orders_archive. |
| 8. Reinspection | Ptah Core, YDB provider, YDB server | The next run reads and compares again. | Schema is synced, no changes to be made. |

### Scenarios

| Scenario | Changed fact | Decided by | Outcome |
| --- | --- | --- | --- |
| Normal creation | Every object is declared, and shop is empty. | Each owner reports its own changes; Core orders them. | Four operations; the transfer is created last. |
| Valid no-op | Every object is declared, and the database already holds all four as declared. | ydb-transfers runs its dependency checks, and they pass. | Schema is synced, no changes to be made. |
| Missing source | The schema leaves out the changefeed feed of orders, and the database has none. | ydb-transfers, before anything is planned. | Refused: the transfer reads a topic the plan leaves absent. |
| Unrepresentable source, current context | The tables exist, and orders holds a changefeed whose consumer names a codec Ptah does not declare. The schema leaves the changefeed out. The host and the provider negotiate models.current-context. | ydb-transfers, from the current context. | The transfer is created; the plan neither drops nor changes the changefeed. |
| Unrepresentable source, no current context | The same database and schema, with a host or a provider that does not negotiate models.current-context, such as Ptah v0.24.1 or YDB plugin v0.7.0. | ydb-transfers, without the read's facts about changefeeds. | Refused as a transfer of a missing topic. |

Steps whose result differs from a normal creation:

| Scenario | Step | Result |
| --- | --- | --- |
| Valid no-op | Reading | All four objects, as the read found them, and complete coverage of shop. |
| Valid no-op | Comparison | A request with the transfer in desired and in current, and the changefeed set of orders in currentContext. |
| Valid no-op | Changes or refusal | No change: the source and the target are declared, and the transfer matches its declaration. |
| Valid no-op | Planning | Nothing to plan. |
| Valid no-op | Review and execution | Nothing runs: Schema is synced, no changes to be made. |
| Missing source | Comparison | A request in which declaredFacets holds no changefeed of orders, and currentContext holds none. |
| Missing source | Changes or refusal | Refused: it reads topic shop/orders/feed, which the schema declares neither as a topic nor as a changefeed, so the plan leaves no such topic. |
| Missing source | Planning | Not reached: the run stops at the refusal. |
| Missing source | Review and execution | Not reached: the run stops at the refusal. |
| Missing source | Reinspection | Not reached: the run stops at the refusal. |
| Unrepresentable source, current context | Reading | Both tables, and the changefeed set of orders recorded as unrepresentable, with no value. |
| Unrepresentable source, current context | Comparison | A request whose currentContext carries that coverage record of orders. |
| Unrepresentable source, current context | Changes or refusal | One new transfer. Its source stays after the plan, because the plan does not drop what the read could not describe. |
| Unrepresentable source, current context | Planning | One operation: the transfer. |
| Unrepresentable source, current context | Review and execution | CREATE TRANSFER runs. Nothing checked the changefeed's definition. |
| Unrepresentable source, current context | Reinspection | Nothing to plan for the transfer. |
| Unrepresentable source, no current context | Selection | A session, without models.current-context among the negotiated features. |
| Unrepresentable source, no current context | Reading | Both tables, and the changefeed set of orders recorded as unrepresentable, with no value. |
| Unrepresentable source, no current context | Comparison | A request without currentContext. |
| Unrepresentable source, no current context | Changes or refusal | Refused: it reads topic shop/orders/feed, which the schema declares neither as a topic nor as a changefeed. |
| Unrepresentable source, no current context | Planning | Not reached: the run stops at the refusal. |
| Unrepresentable source, no current context | Review and execution | Not reached: the run stops at the refusal. |
| Unrepresentable source, no current context | Reinspection | Not reached: the run stops at the refusal. |

The test that measures each scenario:

| Scenario | Test |
| --- | --- |
| Normal creation | [`TestHostCreatesATransferAfterItsChangefeed_HappyPath`](https://github.com/stokaro/ptah-ydb-plugin/blob/24d982d5c88aaa0e474e40a840dc5d4074a9b54e/integration/host_transfer_order_test.go) |
| Valid no-op | [`TestHostCreatesATransferAfterItsChangefeed_HappyPath`](https://github.com/stokaro/ptah-ydb-plugin/blob/24d982d5c88aaa0e474e40a840dc5d4074a9b54e/integration/host_transfer_order_test.go) |
| Missing source | [`TestHostRefusesATransferOfAnUndeclaredChangefeed_FailurePath`](https://github.com/stokaro/ptah-ydb-plugin/blob/24d982d5c88aaa0e474e40a840dc5d4074a9b54e/integration/host_replication_test.go) |
| Unrepresentable source, current context | [`TestHostCreatesATransferOfAChangefeedItCannotDescribe_HappyPath`](https://github.com/stokaro/ptah-ydb-plugin/blob/24d982d5c88aaa0e474e40a840dc5d4074a9b54e/integration/host_transfer_recorded_source_test.go) |
| Unrepresentable source, no current context | [`TestTransferComparisonAcceptsARecordedSource_FailurePath`](https://github.com/stokaro/ptah-ydb-plugin/blob/24d982d5c88aaa0e474e40a840dc5d4074a9b54e/internal/backend/replication_test.go) |

### Connections

| Connection | Kind |
| --- | --- |
| orders → orders/feed: row changes, written by YDB | Data flow in YDB |
| orders/feed → ingest_orders: messages, read by the transfer | Data flow in YDB |
| ingest_orders → orders_archive: rows, written by YDB | Data flow in YDB |
| Ptah Core → YDB provider: DecodeSource and NormalizeValues | Call |
| Ptah Core → YDB provider: Describe and Open | Call |
| Ptah Core → YDB provider: Inspect | Call |
| Ptah Core → YDB provider: CompareModels | Call |
| Ptah Core → YDB provider: PlanFeatures | Call |
| Ptah Core → YDB provider: Render and Execute | Call |
| YDB provider → YDB server: catalog reads | Call |
| YDB provider → YDB server: YQL statements | Call |
| ingest_orders → orders/feed: reads it; the transfer names its topic as a required object | Model dependency |
| ingest_orders → orders_archive: writes it; it has to be a declared table | Model dependency |
| orders/feed → orders: is a facet of it and exists only with it | Model dependency |
| orders → orders/feed: the table is created before its changefeed | Execution order |
| orders/feed → ingest_orders: the changefeed is created before the transfer | Execution order |
| orders_archive → ingest_orders: the target table is created before the transfer | Execution order |

{/* End of the generated walkthrough text. */}
