Skip to content

1. Merge pipeline approaches

Date: 2026-02-06

Status

Accepted

Context

In the Dutch digital heritage network, two approaches for RDF pipelines co-exist:

  • Dataset Knowledge Graph (DKG): analyses datasets to produce VoID summaries of resource aggregates;
  • LD Workbench: a CLI tool for transforming a dataset via SPARQL (iterator/generator pattern over resources)

Both share the same fundamental pattern: resolve distributions (importing them if needed), select items, run SPARQL CONSTRUCT queries, write results.

Where they differ is primarily in scope (multi-dataset vs. single-dataset) and iteration granularity (dataset-level aggregation vs. per-resource transformation).

Shared components

ComponentDKGLD Workbench
Item selectionRegistrySelector (datasets from DCAT-AP registry)Iterator (SELECT query paginating over resource URIs)
Query executionSPARQL CONSTRUCT per analysis dimensionGenerator (CONSTRUCT per resource, with $this binding)
Distribution handlingImport RDF dumps into QLever for queryingImport into local graph store, then query
OutputFiles + GraphDBFiles + TriplyDB
Stage chainingNot used (parallel analysis stages)Sequential: output of stage N feeds into stage N+1

Limitations of the current separation

  • Duplicated infrastructure: both projects independently implement SPARQL streaming, file writing, distribution import and endpoint management and test setup.
  • Divergent conventions: DKG uses custom classes per analysis type; LD Workbench uses EventEmitter hierarchies. Neither approach is easily extensible by third parties.

Decision

Merge the two approaches into a unified pipeline framework.

The shared abstractions become @lde/pipeline:

LD WorkbenchDKGLDE unified
IteratorRegistrySelectorSelector (interface)
GeneratorPer-analysis classesExecutor (interface)
$this binding?dataset, ?classNamed variable bindings
File / TriplyDBFile / GraphDBWriter (interface)
YAML configHardcoded TypeScriptTypeScript API + YAML
EventEmitter flowCustom async classesasync/await + iterables

Pipeline Architecture

The core model:

  • Selector: produces items to iterate (datasets, resources, classes)
  • Executor: runs SPARQL CONSTRUCT queries, produces quads; decorated for domain-specific concerns (e.g. VocabularyExecutor)
  • Writer: consumes quads (file, SPARQL store)
  • Stage: orchestrator that owns the loop: selector iteration → executor batching → writer dispatch
  • Pipeline plugins: lifecycle hooks for concerns like provenance (provenancePlugin()).

Key design principles:

  • Streaming by default: all components stream quads; no materialisation to Store on the main path
  • Composition via decoration: executors wrap other executors (decorator pattern), not inheritance
  • async/await, not EventEmitter: control flow is explicit; EventEmitter only for progress observation
  • Bounded concurrency: maxConcurrency + Promise.race() caps in-flight work to prevent unbounded memory growth
  • Configuration is code: TypeScript objects, not builder chains; readable by both humans and AI agents

Move the VoID-specific code to a separate package @lde/pipeline-void.

Consequences

  • A single, coherent way to build RDF pipelines, whether for analysis or transformation.
  • Shared thus faster development for both approaches.
  • DKG becomes a consumer of @lde/pipeline and @lde/pipeline-void, no longer maintaining its own pipeline infrastructure.
  • LD Workbench users get a migration path to LDE with improved concurrency, memory management and extensibility.
  • Third-party developers can build custom pipeline stages using the same interfaces as built-in ones.
  • LD Workbench’s YAML configuration support is planned as a secondary interface on top of the TypeScript API.

Released under the MIT License.