@lde/search-indexer 0.0.3 → 0.0.4
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/README.md +6 -138
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -7,18 +7,11 @@ projects each root type per the schema, and rebuilds the engine collections –
|
|
|
7
7
|
then exits. Run it as a cron job; the rebuild writers’ cross-pod lock makes an
|
|
8
8
|
overlapping run fail fast instead of corrupting a collection.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
[`@lde/search-api-server`](../search-api-server)
|
|
12
|
-
([#652](https://github.com/ldelements/lde/issues/652)): the composition layer
|
|
13
|
-
that binds the engine-agnostic `searchIndexerPipeline` to the
|
|
14
|
-
[`@lde/search-typesense`](../search-typesense) rebuild writers. Mount the
|
|
15
|
-
**same schema module** into both images and point both at the same
|
|
16
|
-
`TYPESENSE_*` coordinates, and the write and the read side cannot disagree
|
|
17
|
-
about the schema. A deployment that needs more – a bespoke root selector,
|
|
18
|
-
per-stage tuning, another engine – composes `searchStages`,
|
|
19
|
-
`searchIndexWriter` and `Pipeline` directly instead.
|
|
10
|
+
## Installation
|
|
20
11
|
|
|
21
|
-
|
|
12
|
+
```sh
|
|
13
|
+
npm install @lde/search-indexer
|
|
14
|
+
```
|
|
22
15
|
|
|
23
16
|
```sh
|
|
24
17
|
docker run --rm \
|
|
@@ -29,131 +22,6 @@ docker run --rm \
|
|
|
29
22
|
ghcr.io/ldelements/search-indexer
|
|
30
23
|
```
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```sh
|
|
35
|
-
npx @lde/search-indexer
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Dataset IRIs can also be passed as arguments, which override `DATASETS`:
|
|
39
|
-
|
|
40
|
-
```sh
|
|
41
|
-
npx @lde/search-indexer https://example.org/id/dataset/1
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`--check` validates the configuration and schema module, then exits without
|
|
45
|
-
indexing – for CI and init containers.
|
|
46
|
-
|
|
47
|
-
## The schema module
|
|
48
|
-
|
|
49
|
-
The mounted module default-exports the deployment’s search type declarations
|
|
50
|
-
as **plain data** – see [the API server’s
|
|
51
|
-
README](../search-api-server/README.md#the-schema-module) for the format and
|
|
52
|
-
authoring guidance; both images load the module with the same
|
|
53
|
-
`@lde/search/module` loader. The indexer reads only the default export: the
|
|
54
|
-
declarations drive one pipeline stage and one engine collection per root type,
|
|
55
|
-
and each field’s `path` drives the extraction CONSTRUCT. The read-side extras
|
|
56
|
-
(`schemaOptions`, `engineOptions`) are ignored here, so one file serves both
|
|
57
|
-
images.
|
|
58
|
-
|
|
59
|
-
## Configuration
|
|
60
|
-
|
|
61
|
-
| Variable | Default | Meaning |
|
|
62
|
-
| -------------------- | --------------------------- | --------------------------------------------------------------------------------------------------- |
|
|
63
|
-
| `SCHEMA_MODULE` | `/config/search-schema.mjs` | Path of the mounted schema-declaration module |
|
|
64
|
-
| `REGISTRY_ENDPOINT` | **required** | SPARQL endpoint of the DCAT dataset registry |
|
|
65
|
-
| `DATASETS` | all registry datasets | Dataset IRIs to index (whitespace- or comma-separated) |
|
|
66
|
-
| `DATASET_CRITERIA` | all registry datasets | Registry search criteria as a JSON object (mutually exclusive w/ `DATASETS`) |
|
|
67
|
-
| `TYPESENSE_HOST` | **required** | Typesense host |
|
|
68
|
-
| `TYPESENSE_PORT` | `8108` | Typesense port |
|
|
69
|
-
| `TYPESENSE_PROTOCOL` | `http` | `http` or `https` |
|
|
70
|
-
| `TYPESENSE_API_KEY` | **required** | An admin key: the indexer creates, writes and swaps collections |
|
|
71
|
-
| `REBUILD_MODE` | `in-place` | `in-place` (update the live collection) or `blue-green` (swap on commit) |
|
|
72
|
-
| `COLLECTION_PREFIX` | none | Prefix for every derived collection name (configure the read side to match) |
|
|
73
|
-
| `PROVENANCE_FILE` | none | JSON file remembering per-dataset processing, to skip unchanged datasets |
|
|
74
|
-
| `PIPELINE_VERSION` | none | Version keying the skip decisions; required with `PROVENANCE_FILE` |
|
|
75
|
-
| `QLEVER_IMAGE` | none | Enables the QLever import path (see below), e.g. `adfreiburg/qlever:latest` |
|
|
76
|
-
| `IMPORT_STRATEGY` | `sparql` | `sparql`, `sparqlWithImportFallback` or `import`; requires `QLEVER_IMAGE` |
|
|
77
|
-
| `DATA_DIR` | `/data` | Directory for downloaded dumps and QLever index caches |
|
|
78
|
-
| `QLEVER_NETWORK` | none | Docker network the spawned QLever joins; set when the indexer itself runs containerized (see below) |
|
|
79
|
-
|
|
80
|
-
A misconfigured boot reports **all** problems in one error, not one per crash
|
|
81
|
-
loop. `PROVENANCE_FILE` must sit on a durable volume, and cannot be combined
|
|
82
|
-
with `REBUILD_MODE=blue-green`: a skipped dataset would be missing from the
|
|
83
|
-
fresh collection the swap makes live. Its directory must be writable by the
|
|
84
|
-
image’s runtime user (uid 1000) – the image pre-creates `/provenance` with
|
|
85
|
-
that ownership, so a named volume mounted there just works, while a bind
|
|
86
|
-
mount must be `chown`ed on the host. A run fails at start when the file is
|
|
87
|
-
not writable, instead of silently never skipping.
|
|
88
|
-
|
|
89
|
-
## The QLever import path
|
|
90
|
-
|
|
91
|
-
By default the indexer serves only datasets that publish a live SPARQL
|
|
92
|
-
endpoint (the pipeline’s endpoint-only default). Setting `QLEVER_IMAGE`
|
|
93
|
-
enables the import path: data dumps are downloaded to `DATA_DIR` and imported
|
|
94
|
-
into a QLever instance the **pipeline itself creates and controls** – one
|
|
95
|
-
sibling container per dataset, spawned over the Docker socket
|
|
96
|
-
([ADR 16](../../docs/decisions/0016-ship-the-search-indexer-as-a-config-driven-image.md)
|
|
97
|
-
explains why a statically-declared QLever service cannot work). That requires:
|
|
98
|
-
|
|
99
|
-
- the Docker socket mounted into the indexer container
|
|
100
|
-
(`--volume /var/run/docker.sock:/var/run/docker.sock`), plus a group grant
|
|
101
|
-
to reach it as the image’s non-root user
|
|
102
|
-
(`--group-add $(stat -c %g /var/run/docker.sock)`);
|
|
103
|
-
- `DATA_DIR` on a volume whose **host path is identical** for the indexer and
|
|
104
|
-
the spawned QLever containers – the pipeline passes `DATA_DIR` as a bind
|
|
105
|
-
mount to a sibling container, where it resolves against the host.
|
|
106
|
-
|
|
107
|
-
How the indexer reaches the QLever it spawned depends on where the indexer
|
|
108
|
-
itself runs:
|
|
109
|
-
|
|
110
|
-
- **On the host** (`npx @lde/search-indexer` with Docker available): leave
|
|
111
|
-
`QLEVER_NETWORK` unset. QLever’s port is published on the host and
|
|
112
|
-
addressed as `localhost`.
|
|
113
|
-
- **In a container on a bridge network** (the `docker compose` default): set
|
|
114
|
-
`QLEVER_NETWORK` to a network the indexer is attached to. QLever joins that
|
|
115
|
-
network and is addressed by container name (`qlever-<network>`) instead – a
|
|
116
|
-
containerized indexer’s `localhost` is its own network namespace, so it
|
|
117
|
-
cannot reach a host-published port. Alternatively, run the indexer with
|
|
118
|
-
`network_mode: host` and leave `QLEVER_NETWORK` unset.
|
|
119
|
-
|
|
120
|
-
`QLEVER_NETWORK` must name a network the indexer container is actually
|
|
121
|
-
attached to – for compose, the prefixed name Docker creates (e.g.
|
|
122
|
-
`myproject_default`), not the short service-file name. A wrong or unattached
|
|
123
|
-
network is not caught at boot: each dataset imports fully, then fails when
|
|
124
|
-
the endpoint never becomes reachable. And run at most one indexer per
|
|
125
|
-
network – the QLever container name is derived from the network, so two
|
|
126
|
-
indexers sharing one would remove each other’s QLever.
|
|
127
|
-
|
|
128
|
-
This mode does not work on container runtimes without a Docker socket
|
|
129
|
-
(containerd-based Kubernetes); there, run endpoint-only for now.
|
|
130
|
-
|
|
131
|
-
## Building the image
|
|
132
|
-
|
|
133
|
-
The image is built from the workspace’s own outputs – the compiled package,
|
|
134
|
-
the same-commit builds of its `@lde/*` dependencies and a pruned lockfile –
|
|
135
|
-
never from npm, so it exists for any commit
|
|
136
|
-
([ADR 15](../../docs/decisions/0015-ship-the-served-search-api-as-a-docker-image-built-from-the-workspace.md)):
|
|
137
|
-
|
|
138
|
-
```sh
|
|
139
|
-
npx nx run @lde/search-indexer:docker:build # → packages-search-indexer
|
|
140
|
-
npx nx run @lde/search-indexer:docker:smoke # boots it with --check
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
CI runs `docker:smoke` for affected PRs; each release rebuilds and pushes
|
|
144
|
-
`ghcr.io/ldelements/search-indexer:<version>` (`.github/workflows/docker.yml`).
|
|
25
|
+
## Documentation
|
|
145
26
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
The bin is a thin wrapper over the exported API, usable in tests or a custom
|
|
149
|
-
boot:
|
|
150
|
-
|
|
151
|
-
```ts
|
|
152
|
-
import {
|
|
153
|
-
configFromEnvironment,
|
|
154
|
-
createSearchIndexer,
|
|
155
|
-
} from '@lde/search-indexer';
|
|
156
|
-
|
|
157
|
-
const pipeline = await createSearchIndexer(configFromEnvironment(process.env));
|
|
158
|
-
await pipeline.run();
|
|
159
|
-
```
|
|
27
|
+
See the [full documentation](https://ldelements.org/reference/search-indexer).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lde/search-indexer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "The @lde/search-pipeline indexer as a bootable process and prebuilt Docker image: loads a mounted schema-declaration module, dataset selection, Typesense connection and rebuild mode from the environment, then runs the object-grain searchIndexerPipeline once to completion. The composition layer that binds the engine-agnostic @lde/search-pipeline stages to @lde/search-typesense – the write-path counterpart of @lde/search-api-server.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "git+https://github.com/ldelements/lde.git",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@lde/dataset-registry-client": "^0.9.1",
|
|
32
32
|
"@lde/pipeline": "^0.35.4",
|
|
33
33
|
"@lde/pipeline-console-reporter": "^0.26.4",
|
|
34
|
-
"@lde/search": "^0.12.
|
|
35
|
-
"@lde/search-pipeline": "^0.12.
|
|
36
|
-
"@lde/search-typesense": "^0.15.
|
|
34
|
+
"@lde/search": "^0.12.3",
|
|
35
|
+
"@lde/search-pipeline": "^0.12.6",
|
|
36
|
+
"@lde/search-typesense": "^0.15.6",
|
|
37
37
|
"@lde/sparql-qlever": "^0.15.3",
|
|
38
38
|
"commander": "^15.0.0",
|
|
39
39
|
"tslib": "^2.3.0",
|