meadow-integration 1.0.40 → 1.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUILDING-AND-PUBLISHING.md +2 -2
- package/Dockerfile +1 -1
- package/README.md +27 -8
- package/docs/README.md +1 -1
- package/docs/_brand.json +18 -0
- package/docs/_cover.md +1 -1
- package/docs/_topbar.md +1 -1
- package/docs/_version.json +3 -3
- package/docs/architecture.md +14 -225
- package/docs/data-clone/configuration.md +9 -1
- package/docs/data-clone/diagrams/architecture-diagram.excalidraw +1756 -0
- package/docs/data-clone/diagrams/architecture-diagram.mmd +8 -0
- package/docs/data-clone/diagrams/architecture-diagram.svg +2 -0
- package/docs/data-clone/overview.md +2 -32
- package/docs/diagrams/configuration-cascade-2.excalidraw +831 -0
- package/docs/diagrams/configuration-cascade-2.mmd +8 -0
- package/docs/diagrams/configuration-cascade-2.svg +2 -0
- package/docs/diagrams/configuration-cascade.excalidraw +831 -0
- package/docs/diagrams/configuration-cascade.mmd +8 -0
- package/docs/diagrams/configuration-cascade.svg +2 -0
- package/docs/diagrams/data-synchronization-pipeline.excalidraw +3278 -0
- package/docs/diagrams/data-synchronization-pipeline.mmd +42 -0
- package/docs/diagrams/data-synchronization-pipeline.svg +2 -0
- package/docs/diagrams/data-transformation-pipeline.excalidraw +2929 -0
- package/docs/diagrams/data-transformation-pipeline.mmd +31 -0
- package/docs/diagrams/data-transformation-pipeline.svg +2 -0
- package/docs/diagrams/docker-deployment.excalidraw +1963 -0
- package/docs/diagrams/docker-deployment.mmd +23 -0
- package/docs/diagrams/docker-deployment.svg +2 -0
- package/docs/diagrams/high-level-system-architecture.excalidraw +5752 -0
- package/docs/diagrams/high-level-system-architecture.mmd +66 -0
- package/docs/diagrams/high-level-system-architecture.svg +2 -0
- package/docs/diagrams/module-structure.excalidraw +15206 -0
- package/docs/diagrams/module-structure.mmd +56 -0
- package/docs/diagrams/module-structure.svg +2 -0
- package/docs/diagrams/sync-mode-comparison.excalidraw +3660 -0
- package/docs/diagrams/sync-mode-comparison.mmd +33 -0
- package/docs/diagrams/sync-mode-comparison.svg +2 -0
- package/docs/implementation-reference.md +2 -58
- package/docs/index.html +6 -7
- package/docs/retold-catalog.json +388 -279
- package/docs/retold-keyword-index.json +24887 -16186
- package/example-applications/mapping-demo/README.md +2 -10
- package/example-applications/mapping-demo/diagrams/architecture.excalidraw +1866 -0
- package/example-applications/mapping-demo/diagrams/architecture.mmd +8 -0
- package/example-applications/mapping-demo/diagrams/architecture.svg +2 -0
- package/example-applications/mapping-demo/package.json +22 -1
- package/example-applications/mapping-demo/server.js +28 -0
- package/example-applications/mapping-demo/source/MappingDemoApp.js +42 -3
- package/example-applications/mapping-demo/source/MappingDemoBrand.js +17 -0
- package/example-applications/mapping-demo/web/favicons/apple-touch-icon.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-16.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-192.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-32.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-48.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-512.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-64.png +0 -0
- package/example-applications/mapping-demo/web/favicons/favicon-dark.svg +30 -0
- package/example-applications/mapping-demo/web/favicons/favicon-light.svg +30 -0
- package/example-applications/mapping-demo/web/favicons/favicon.svg +30 -0
- package/example-applications/mapping-demo/web/index.html +40 -26
- package/example-applications/mapping-demo/web/mapping-demo-editor.js +3267 -398
- package/example-applications/mapping-demo/web/mapping-demo-editor.js.map +1 -1
- package/example-applications/mapping-demo/web/mapping-demo-editor.min.js +34 -1
- package/example-applications/mapping-demo/web/mapping-demo-editor.min.js.map +1 -1
- package/example-applications/mapping-demo/web/pict.min.js +2 -2
- package/package.json +10 -7
- package/source/services/clone/Meadow-Service-DeleteCursorStore.js +105 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-OngoingEventualConsistency.js +327 -92
- package/source/services/clone/Meadow-Service-Sync.js +2 -0
- package/source/views/PictView-MeadowMappingEditor.js +30 -30
- package/test/Meadow-Integration-BisectionSync_test.js +15 -5
- package/test/Meadow-Integration-NewStrategies_test.js +15 -5
- package/test/Meadow-Integration-OngoingEventualConsistencyDeleteCursor_test.js +228 -0
- package/test/Meadow-Integration-OngoingEventualConsistencyDeleteSync_test.js +311 -0
|
@@ -39,7 +39,7 @@ the plain `release:patch` ships to npm and skips the image rebuild.
|
|
|
39
39
|
`npm login`.
|
|
40
40
|
- **Git remote configured** — `git remote get-url origin` should print
|
|
41
41
|
the GitHub HTTPS or SSH URL. If not, `git remote add origin
|
|
42
|
-
git@github.com:
|
|
42
|
+
git@github.com:fable-retold/meadow-integration.git`.
|
|
43
43
|
- **Push access to the repo** — required so `postversion` /
|
|
44
44
|
`postpublish` can push the tag. The GHCR workflow runs under
|
|
45
45
|
`GITHUB_TOKEN` so no extra registry auth needed for image pushing.
|
|
@@ -187,7 +187,7 @@ After `release:patch` completes:
|
|
|
187
187
|
1. **npm**: `npm view meadow-integration version` should print the new
|
|
188
188
|
version (may take ~30s for the registry to update).
|
|
189
189
|
2. **GHCR workflow**: visit
|
|
190
|
-
`https://github.com/
|
|
190
|
+
`https://github.com/fable-retold/meadow-integration/actions` and
|
|
191
191
|
confirm the "Publish container image" run succeeded.
|
|
192
192
|
3. **Image**: `docker pull ghcr.io/stevenvelozo/meadow-integration:<version>`
|
|
193
193
|
should succeed. The image is also tagged as `latest`, `<major>`, and
|
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Meadow Integration
|
|
2
2
|
|
|
3
|
+
> **[Read the Meadow-Integration Documentation](https://fable-retold.github.io/meadow-integration/)** - interactive docs with the full API reference.
|
|
4
|
+
|
|
3
5
|
A suite of tools for managing data into a centralized non-specific schema format called a **Comprehension**.
|
|
4
6
|
|
|
5
|
-
These tools are built to be usable from the command-line, as a web service, or within your own codebase. This module presents these behaviors both as a suite of externally usable fable services, a command-line utility to
|
|
7
|
+
These tools are built to be usable from the command-line, as a web service, or within your own codebase. This module presents these behaviors both as a suite of externally usable fable services, a command-line utility to use them and a set of web service behaviors.
|
|
6
8
|
|
|
7
9
|
## What is a Comprehension?
|
|
8
10
|
|
|
@@ -230,6 +232,23 @@ The `data-clone` command synchronizes entity data from a remote Meadow REST API
|
|
|
230
232
|
|------|-------------|
|
|
231
233
|
| **Initial** | Compares the max entity ID on the server against the local database and downloads all records with IDs greater than the local maximum. Designed for first-time bulk population. |
|
|
232
234
|
| **Ongoing** | Walks through all server records page by page, comparing `UpdateDate` timestamps. Creates missing records locally and updates records whose server timestamp is newer than the local copy. |
|
|
235
|
+
| **OngoingEventualConsistency** | Time-budgeted variant of Ongoing: bisects the id range newest-first within `BackSyncTimeLimit`, then pulls new tail records. Reconciles deleted records separately (see below). |
|
|
236
|
+
| **TrueUp** | Forward keyset walk of the whole server range to repair gaps/drift. |
|
|
237
|
+
|
|
238
|
+
### Deleted-record reconciliation
|
|
239
|
+
|
|
240
|
+
When `SyncDeletedRecords` is enabled, `OngoingEventualConsistency` reconciles server-side deletions into the local clone. Each deleted server row is matched to the local row by **identity only** — never by GUID, because GUIDs are not guaranteed unique in cloned data and a GUID match could soft-delete the wrong record — and flagged via `doDelete`. Rows whose id is not present locally are counted and skipped (not created). Processing is newest-first by the indexed id, within `BackSyncTimeLimit`.
|
|
241
|
+
|
|
242
|
+
#### Resumable cursor options
|
|
243
|
+
|
|
244
|
+
By default each run sweeps the deleted set newest-first from the top, which on a large backlog never reaches older records within the time budget. These options make the sweep resumable:
|
|
245
|
+
|
|
246
|
+
| Option | Description |
|
|
247
|
+
|--------|-------------|
|
|
248
|
+
| `DeleteCursorStatePath` | (Optional) Path to a JSON file persisting per-table head/tail id marks so each run resumes the deleted-record sweep instead of re-walking from the newest record. Unset = disabled. The file must persist between runs to be useful; a missing/corrupt file degrades safely to a full sweep. Holds only a few integers per table — no record data. |
|
|
249
|
+
| `DeleteResweepIntervalHours` | (Optional, default `168`) Once the backlog is drained, hours between full re-sweeps that catch deletions of older records landing in already-swept id ranges. |
|
|
250
|
+
|
|
251
|
+
With the cursor enabled, each run runs a cheap **head pass** (`id > headID`, new deletions since last run) then continues the **tail** (`id < tailID`) within budget, using keyset paging (no growing `OFFSET`). Options propagate via `MeadowSync` options / per-entity `SyncEntityOptions`, and the strategy also reads matching keys from `fable.settings`.
|
|
233
252
|
|
|
234
253
|
### CLI Options
|
|
235
254
|
|
|
@@ -328,13 +347,13 @@ npm test
|
|
|
328
347
|
|
|
329
348
|
## Related Packages
|
|
330
349
|
|
|
331
|
-
- [meadow](https://github.com/
|
|
332
|
-
- [meadow-endpoints](https://github.com/
|
|
333
|
-
- [meadow-connection-mysql](https://github.com/
|
|
334
|
-
- [meadow-connection-mssql](https://github.com/
|
|
335
|
-
- [orator](https://github.com/
|
|
336
|
-
- [fable](https://github.com/
|
|
337
|
-
- [pict-service-commandlineutility](https://github.com/
|
|
350
|
+
- [meadow](https://github.com/fable-retold/meadow) - Data access and ORM
|
|
351
|
+
- [meadow-endpoints](https://github.com/fable-retold/meadow-endpoints) - Auto-generated REST endpoints
|
|
352
|
+
- [meadow-connection-mysql](https://github.com/fable-retold/meadow-connection-mysql) - MySQL database provider for Meadow
|
|
353
|
+
- [meadow-connection-mssql](https://github.com/fable-retold/meadow-connection-mssql) - MSSQL database provider for Meadow
|
|
354
|
+
- [orator](https://github.com/fable-retold/orator) - API server abstraction
|
|
355
|
+
- [fable](https://github.com/fable-retold/fable) - Application services framework
|
|
356
|
+
- [pict-service-commandlineutility](https://github.com/fable-retold/pict-service-commandlineutility) - CLI framework with cascading configuration
|
|
338
357
|
|
|
339
358
|
## License
|
|
340
359
|
|
package/docs/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A suite of tools for managing data into a centralized non-specific schema format called a **Comprehension**.
|
|
4
4
|
|
|
5
|
-
These tools are built to be usable from the command-line, as a web service, or within your own codebase. This module presents these behaviors both as a suite of externally usable fable services, a command-line utility to
|
|
5
|
+
These tools are built to be usable from the command-line, as a web service, or within your own codebase. This module presents these behaviors both as a suite of externally usable fable services, a command-line utility to use them and a set of web service behaviors.
|
|
6
6
|
|
|
7
7
|
In addition to data transformation, Meadow Integration includes a **Data Clone** pipeline for replicating entity data from a remote Meadow REST API into a local MySQL or MSSQL database.
|
|
8
8
|
|
package/docs/_brand.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"Hash": "meadow-integration",
|
|
3
|
+
"Name": "Meadow Integration",
|
|
4
|
+
"Tagline": "Data integration tools for CSV import, schema mapping, and centralized format transformations",
|
|
5
|
+
"Palette": "mix",
|
|
6
|
+
"Icon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"frame-meadow-integration-filled-light\">\n\t\t\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\" fill=\"#c67445\"/>\n\t\t<g clip-path=\"url(#frame-meadow-integration-filled-light)\"><path d=\"M 16 70 L 48 30 L 80 70 Z\" fill=\"rgba(255,255,255,0.18)\"/>\n\t\t\t\t\t<path d=\"M 24 80 L 48 52 L 72 80 Z\" fill=\"#49b2c1\" opacity=\"0.9\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"38\" font-weight=\"700\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">MI</text>\n\t</svg>",
|
|
7
|
+
"IconType": "svg",
|
|
8
|
+
"Favicon": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-meadow-integration-light\">\n\t\t\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\" fill=\"#c67445\"/>\n\t\t<g clip-path=\"url(#fav-meadow-integration-light)\"><path d=\"M 16 70 L 48 30 L 80 70 Z\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#ffffff\" letter-spacing=\"-1\">M</text>\n\t</svg>",
|
|
9
|
+
"FaviconDark": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 96 96\" width=\"96\" height=\"96\">\n\t\t<defs>\n\t\t\t<clipPath id=\"fav-meadow-integration-dark\">\n\t\t\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\"/>\n\t\t\t</clipPath>\n\t\t</defs>\n\t\t<path d=\"M 24 2\n\t\tH 72\n\t\tQ 94 2 94 24\n\t\tV 72\n\t\tQ 94 94 72 94\n\t\tH 24\n\t\tQ 2 94 2 72\n\t\tV 24\n\t\tQ 2 2 24 2 Z\" fill=\"#d7aa90\"/>\n\t\t<g clip-path=\"url(#fav-meadow-integration-dark)\"><path d=\"M 16 70 L 48 30 L 80 70 Z\" fill=\"rgba(255,255,255,0.22)\"/></g>\n\t\t<text x=\"48\" y=\"50\" text-anchor=\"middle\" dominant-baseline=\"central\"\n\t\t\tfont-family=\"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif\"\n\t\t\tfont-size=\"60\" font-weight=\"800\"\n\t\t\tfill=\"#101418\" letter-spacing=\"-1\">M</text>\n\t</svg>",
|
|
10
|
+
"Colors": {
|
|
11
|
+
"Primary": "#c67445",
|
|
12
|
+
"Secondary": "#49b2c1",
|
|
13
|
+
"PrimaryLight": "#c67445",
|
|
14
|
+
"PrimaryDark": "#d7aa90",
|
|
15
|
+
"SecondaryLight": "#49b2c1",
|
|
16
|
+
"SecondaryDark": "#92ccd4"
|
|
17
|
+
}
|
|
18
|
+
}
|
package/docs/_cover.md
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
- Synchronize remote Meadow APIs to local databases
|
|
9
9
|
- CLI utility, programmatic API, and REST integration
|
|
10
10
|
|
|
11
|
-
[GitHub](https://github.com/
|
|
11
|
+
[GitHub](https://github.com/fable-retold/meadow-integration)
|
|
12
12
|
[Get Started](#meadow-integration)
|
package/docs/_topbar.md
CHANGED
package/docs/_version.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Name": "meadow-integration",
|
|
3
|
-
"Version": "1.0.
|
|
3
|
+
"Version": "1.0.41",
|
|
4
4
|
"Description": "Meadow Data Integration",
|
|
5
|
-
"GeneratedAt": "2026-
|
|
6
|
-
"GitCommit": "
|
|
5
|
+
"GeneratedAt": "2026-05-26T21:12:33.932Z",
|
|
6
|
+
"GitCommit": "170b8fe"
|
|
7
7
|
}
|
package/docs/architecture.md
CHANGED
|
@@ -6,74 +6,8 @@ This document describes the architectural design of Meadow Integration, covering
|
|
|
6
6
|
|
|
7
7
|
Meadow Integration sits between external data sources and the Meadow data access layer. It provides three interfaces (CLI, REST, Programmatic) that share a common set of services.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
subgraph External["External Data Sources"]
|
|
12
|
-
CSV["CSV Files"]
|
|
13
|
-
TSV["TSV Files"]
|
|
14
|
-
JSON["JSON Arrays"]
|
|
15
|
-
API["Remote Meadow API"]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
subgraph Interfaces["Interfaces"]
|
|
19
|
-
CLI["CLI Program\n(pict-service-commandlineutility)"]
|
|
20
|
-
REST["REST Server\n(Orator + Restify)"]
|
|
21
|
-
PROG["Programmatic API\n(require meadow-integration)"]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
subgraph Services["Core Services"]
|
|
25
|
-
TC["TabularCheck"]
|
|
26
|
-
TT["TabularTransform"]
|
|
27
|
-
IA["IntegrationAdapter"]
|
|
28
|
-
GM["GUIDMap"]
|
|
29
|
-
CM["ConnectionManager"]
|
|
30
|
-
CRC["CloneRestClient"]
|
|
31
|
-
SYNC["Sync"]
|
|
32
|
-
SEI["SyncEntityInitial"]
|
|
33
|
-
SEO["SyncEntityOngoing"]
|
|
34
|
-
OP["Operation"]
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
subgraph Targets["Targets"]
|
|
38
|
-
MAPI["Meadow REST API\n(write)"]
|
|
39
|
-
DB["Local Database\n(MySQL / MSSQL)"]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
CSV --> CLI
|
|
43
|
-
TSV --> CLI
|
|
44
|
-
JSON --> CLI
|
|
45
|
-
CSV --> REST
|
|
46
|
-
TSV --> REST
|
|
47
|
-
JSON --> REST
|
|
48
|
-
|
|
49
|
-
CLI --> TC
|
|
50
|
-
CLI --> TT
|
|
51
|
-
CLI --> IA
|
|
52
|
-
CLI --> SYNC
|
|
53
|
-
REST --> TC
|
|
54
|
-
REST --> TT
|
|
55
|
-
REST --> IA
|
|
56
|
-
PROG --> TC
|
|
57
|
-
PROG --> TT
|
|
58
|
-
PROG --> IA
|
|
59
|
-
PROG --> SYNC
|
|
60
|
-
|
|
61
|
-
TT --> IA
|
|
62
|
-
IA --> GM
|
|
63
|
-
IA --> MAPI
|
|
64
|
-
|
|
65
|
-
API --> CRC
|
|
66
|
-
CRC --> SYNC
|
|
67
|
-
SYNC --> SEI
|
|
68
|
-
SYNC --> SEO
|
|
69
|
-
SEI --> CM
|
|
70
|
-
SEO --> CM
|
|
71
|
-
CM --> DB
|
|
72
|
-
|
|
73
|
-
SYNC --> OP
|
|
74
|
-
SEI --> OP
|
|
75
|
-
SEO --> OP
|
|
76
|
-
```
|
|
9
|
+
<!-- bespoke diagram: edit diagrams/high-level-system-architecture.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
10
|
+

|
|
77
11
|
|
|
78
12
|
The system divides cleanly into two pipelines that share the `Operation` utility for timing and progress tracking.
|
|
79
13
|
|
|
@@ -81,39 +15,8 @@ The system divides cleanly into two pipelines that share the `Operation` utility
|
|
|
81
15
|
|
|
82
16
|
The transformation pipeline converts tabular data into Meadow entity records. Each stage is a discrete service that can be used independently.
|
|
83
17
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
subgraph Input["1. Parse"]
|
|
87
|
-
FILE["Source File\n(CSV / TSV / JSON)"]
|
|
88
|
-
PARSE["Stream Parser\n(csv-parser / JSON.parse)"]
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
subgraph Transform["2. Transform"]
|
|
92
|
-
RECORD["Raw Record"]
|
|
93
|
-
MAPPING["Mapping Config\n(Implicit + Explicit + User)"]
|
|
94
|
-
TEMPLATE["Pict Template Engine\n({~D:Record.col~})"]
|
|
95
|
-
SOLVER["Solvers\n(Expression Parser)"]
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
subgraph Collect["3. Collect"]
|
|
99
|
-
COMP["Comprehension\n{Entity: {GUID: Record}}"]
|
|
100
|
-
MERGE["Intersect\n(merge by GUID)"]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
subgraph Push["4. Push"]
|
|
104
|
-
ADAPTER["IntegrationAdapter"]
|
|
105
|
-
MARSHAL["Marshal Record\n(schema validation,\nstring truncation,\nGUID prefixing)"]
|
|
106
|
-
GUIDMAP["GUIDMap\n(external <-> Meadow IDs)"]
|
|
107
|
-
UPSERT["Upsert\n(single or bulk)"]
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
FILE --> PARSE --> RECORD
|
|
111
|
-
MAPPING --> TEMPLATE
|
|
112
|
-
RECORD --> TEMPLATE --> COMP
|
|
113
|
-
RECORD --> SOLVER --> COMP
|
|
114
|
-
COMP --> MERGE --> COMP
|
|
115
|
-
COMP --> ADAPTER --> MARSHAL --> GUIDMAP --> UPSERT
|
|
116
|
-
```
|
|
18
|
+
<!-- bespoke diagram: edit diagrams/data-transformation-pipeline.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
19
|
+

|
|
117
20
|
|
|
118
21
|
### Stage Details
|
|
119
22
|
|
|
@@ -137,50 +40,8 @@ Pict template expressions resolve column values at transformation time. Solvers
|
|
|
137
40
|
|
|
138
41
|
The Data Clone pipeline replicates entity data from a remote Meadow API into a local relational database.
|
|
139
42
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
subgraph Config["Configuration"]
|
|
143
|
-
MCFG[".meadow.config.json"]
|
|
144
|
-
SCHEMA["Extended Schema JSON\n(from Stricture)"]
|
|
145
|
-
CLIOPTS["CLI Overrides\n(--api_server, --db_host, etc.)"]
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
subgraph Auth["1. Authenticate"]
|
|
149
|
-
CRC["CloneRestClient"]
|
|
150
|
-
SESSION["Session Management\n(cookie / token)"]
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
subgraph Connect["2. Connect"]
|
|
154
|
-
CM["ConnectionManager"]
|
|
155
|
-
POOL["Connection Pool\n(MySQL or MSSQL)"]
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
subgraph Init["3. Initialize Schema"]
|
|
159
|
-
LOAD["Load Extended Schema"]
|
|
160
|
-
CREATE["Create Tables\n(if not exist)"]
|
|
161
|
-
INDEX["Create Indexes\n(GUID unique, Deleted)"]
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
subgraph Sync["4. Sync Entities"]
|
|
165
|
-
COMPARE["Compare\nlocal vs. remote\n(max ID, count, UpdateDate)"]
|
|
166
|
-
DOWNLOAD["Download Pages\n(filtered + sorted)"]
|
|
167
|
-
WRITE["Marshal + Write\n(create or update)"]
|
|
168
|
-
PROGRESS["Progress Tracking\n(Operation service)"]
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
MCFG --> CRC
|
|
172
|
-
CLIOPTS --> CRC
|
|
173
|
-
MCFG --> CM
|
|
174
|
-
CLIOPTS --> CM
|
|
175
|
-
SCHEMA --> LOAD
|
|
176
|
-
|
|
177
|
-
CRC --> SESSION --> DOWNLOAD
|
|
178
|
-
CM --> POOL --> WRITE
|
|
179
|
-
LOAD --> CREATE --> INDEX
|
|
180
|
-
|
|
181
|
-
COMPARE --> DOWNLOAD --> WRITE
|
|
182
|
-
WRITE --> PROGRESS
|
|
183
|
-
```
|
|
43
|
+
<!-- bespoke diagram: edit diagrams/data-synchronization-pipeline.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
44
|
+

|
|
184
45
|
|
|
185
46
|
### Stage Details
|
|
186
47
|
|
|
@@ -317,69 +178,20 @@ classDiagram
|
|
|
317
178
|
|
|
318
179
|
Configuration for the CLI flows through multiple layers, each overriding the previous.
|
|
319
180
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
DEF["Default Configuration\n(Default-Meadow-Integration-\nConfiguration.json)"]
|
|
323
|
-
FILE[".meadow.config.json\n(working directory)"]
|
|
324
|
-
CLI["Command-Line Flags\n(--api_server, --db_host, etc.)"]
|
|
325
|
-
|
|
326
|
-
DEF -->|"base"| MERGED["Resolved Configuration"]
|
|
327
|
-
FILE -->|"overrides"| MERGED
|
|
328
|
-
CLI -->|"overrides"| MERGED
|
|
329
|
-
```
|
|
181
|
+
<!-- bespoke diagram: edit diagrams/configuration-cascade.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
182
|
+

|
|
330
183
|
|
|
331
184
|
For data transformation, the mapping configuration has its own three-layer cascade:
|
|
332
185
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
IMP["Implicit\n(auto-detected from\nfirst record)"]
|
|
336
|
-
EXP["Explicit\n(mapping file\nvia -m flag)"]
|
|
337
|
-
USR["User\n(CLI flags:\n-e, -g, -n, -c)"]
|
|
338
|
-
|
|
339
|
-
IMP -->|"base"| FINAL["Final Mapping Config"]
|
|
340
|
-
EXP -->|"overrides"| FINAL
|
|
341
|
-
USR -->|"overrides"| FINAL
|
|
342
|
-
```
|
|
186
|
+
<!-- bespoke diagram: edit diagrams/configuration-cascade-2.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
187
|
+

|
|
343
188
|
|
|
344
189
|
## Sync Mode Comparison
|
|
345
190
|
|
|
346
191
|
The two sync modes serve different purposes and have different performance characteristics.
|
|
347
192
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
subgraph Initial["Initial Sync"]
|
|
351
|
-
I1["Query local max ID"]
|
|
352
|
-
I2["Query remote max ID + count"]
|
|
353
|
-
I3["Generate paginated URL partials\n(filter: ID > local max)"]
|
|
354
|
-
I4["Download each page"]
|
|
355
|
-
I5["For each record:\nRead local by ID"]
|
|
356
|
-
I6{"Record\nexists?"}
|
|
357
|
-
I7["Skip"]
|
|
358
|
-
I8["Create with\nidentity insert"]
|
|
359
|
-
|
|
360
|
-
I1 --> I2 --> I3 --> I4 --> I5 --> I6
|
|
361
|
-
I6 -->|"yes"| I7
|
|
362
|
-
I6 -->|"no"| I8
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
subgraph Ongoing["Ongoing Sync"]
|
|
366
|
-
O1["Query local max ID + UpdateDate"]
|
|
367
|
-
O2["Query remote max ID + UpdateDate + count"]
|
|
368
|
-
O3["Iterate all records\n(paginated, ID ascending)"]
|
|
369
|
-
O4["For each record:\nRead local by ID"]
|
|
370
|
-
O5{"Record\nexists?"}
|
|
371
|
-
O6{"UpdateDate\ndifference\n> 5ms?"}
|
|
372
|
-
O7["Update record"]
|
|
373
|
-
O8["Skip"]
|
|
374
|
-
O9["Create with\nidentity insert"]
|
|
375
|
-
|
|
376
|
-
O1 --> O2 --> O3 --> O4 --> O5
|
|
377
|
-
O5 -->|"yes"| O6
|
|
378
|
-
O5 -->|"no"| O9
|
|
379
|
-
O6 -->|"yes"| O7
|
|
380
|
-
O6 -->|"no"| O8
|
|
381
|
-
end
|
|
382
|
-
```
|
|
193
|
+
<!-- bespoke diagram: edit diagrams/sync-mode-comparison.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
194
|
+

|
|
383
195
|
|
|
384
196
|
| Aspect | Initial | Ongoing |
|
|
385
197
|
|--------|---------|---------|
|
|
@@ -394,30 +206,7 @@ flowchart TB
|
|
|
394
206
|
|
|
395
207
|
The included Dockerfile builds a production image for running Data Clone as a containerized service. The image is based on `node:20-bookworm` and expects a `.meadow.config.json` to be provided at runtime (via volume mount or baked into a derived image).
|
|
396
208
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
subgraph Build["Docker Build"]
|
|
400
|
-
BASE["node:20-bookworm"]
|
|
401
|
-
DEPS["npm install --omit=dev"]
|
|
402
|
-
SRC["Copy source + scripts"]
|
|
403
|
-
end
|
|
404
|
-
|
|
405
|
-
subgraph Runtime["Docker Runtime"]
|
|
406
|
-
CFG[".meadow.config.json\n(volume mount)"]
|
|
407
|
-
SCHEMA["Extended Schema\n(volume mount)"]
|
|
408
|
-
RUN["scripts/run.sh"]
|
|
409
|
-
end
|
|
410
|
-
|
|
411
|
-
subgraph External["External"]
|
|
412
|
-
REMOTE["Remote Meadow API"]
|
|
413
|
-
LOCAL["Local Database"]
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
BASE --> DEPS --> SRC --> RUN
|
|
417
|
-
CFG --> RUN
|
|
418
|
-
SCHEMA --> RUN
|
|
419
|
-
RUN --> REMOTE
|
|
420
|
-
RUN --> LOCAL
|
|
421
|
-
```
|
|
209
|
+
<!-- bespoke diagram: edit diagrams/docker-deployment.mmd or .hints.json, then: npx pict-renderer-graph build modules/meadow/meadow-integration/docs -->
|
|
210
|
+

|
|
422
211
|
|
|
423
212
|
The `docker-compose.yml` can be used to run the Data Clone alongside a local MySQL or MSSQL container for development and testing.
|
|
@@ -135,20 +135,28 @@ Entities are synced in the order they appear in this list.
|
|
|
135
135
|
|
|
136
136
|
#### SyncEntityOptions
|
|
137
137
|
|
|
138
|
-
Per-entity overrides, keyed by entity name
|
|
138
|
+
Per-entity overrides, keyed by entity name. Values are merged on top of the global `Sync.*` defaults at entity construction (any key accepted by the entity constructor).
|
|
139
|
+
|
|
140
|
+
When the config is consumed via the data-cloner headless pipeline (`retold-data-service-clone --config`, or the `/clone/sync/start` POST route), the following keys also take effect as **runtime overrides per entity** and win over the global runtime values: `BackSyncTimeLimit`, `MaxRecordsPerEntity`, `DateTimePrecisionMS`, `TrueUpPageSize`, `UseAdvancedIDPagination`, `SyncDeletedRecords`.
|
|
139
141
|
|
|
140
142
|
```json
|
|
141
143
|
{
|
|
142
144
|
"Sync": {
|
|
145
|
+
"BackSyncTimeLimit": 30000,
|
|
143
146
|
"SyncEntityOptions": {
|
|
144
147
|
"AuditLog": {
|
|
145
148
|
"PageSize": 500
|
|
149
|
+
},
|
|
150
|
+
"Document": {
|
|
151
|
+
"BackSyncTimeLimit": 600000
|
|
146
152
|
}
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
}
|
|
150
156
|
```
|
|
151
157
|
|
|
158
|
+
In the example above, `Document` gets a 600s bisection budget while every other entity uses the global 30s. Unknown entity names in `SyncEntityOptions` are logged as a warning and ignored.
|
|
159
|
+
|
|
152
160
|
## CLI Flag Overrides
|
|
153
161
|
|
|
154
162
|
All configuration values can be overridden via CLI flags. CLI flags take precedence over values from `.meadow.config.json`.
|