Layer 3: Repository
Domain-specific combinations of multiple stores. Each repository owns one domain concept.
ArchiveRepository
Content-addressed file archive with extracted text and raw data storage.
from ftm_lakehouse import get_archive
archive = get_archive("my_dataset")
checksum = archive.store(uri)
archive.exists(checksum)
archive.stream(checksum)
ftm_lakehouse.repository.ArchiveRepository
Bases: DatasetHandle
Repository for file archive operations.
Content-addressed blob storage (raw bytes): a blob is stored once per checksum.
Optionally, extracted text (by different origins) can be stored and
retrieved. As well, other programs can write arbitrary additional data to
the archive (such as pdf page thumbnails or their own file metadata) via
put_data.
Example
Source code in ftm_lakehouse/repository/archive.py
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | |
exists(checksum)
get_data(checksum, path)
Get raw data at the given path in the checksum's archive directory
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in ftm_lakehouse/repository/archive.py
get_txt(checksum, origin=None)
Get extracted text for a file. If origin, get by this specific
extraction, otherwise get the first txt value (no guaranteed order)
Source code in ftm_lakehouse/repository/archive.py
iterate_checksums()
Iterate the checksums of all blobs in the archive.
Source code in ftm_lakehouse/repository/archive.py
local_path(checksum)
Get the local path to the blob.
If storage is local, returns actual path. Otherwise, creates a temporary local copy that is cleaned up after context exit.
Source code in ftm_lakehouse/repository/archive.py
open(checksum)
put_data(checksum, path, data)
Store raw data at the given path in the checksum's archive directory
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in ftm_lakehouse/repository/archive.py
put_txt(checksum, text, origin=DEFAULT_ORIGIN)
Store extracted text for a file.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in ftm_lakehouse/repository/archive.py
store(uri, checksum=None, tag_updated=True)
Archive a file from a local or remote URI.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uri
|
Uri
|
Local or remote URI to the file |
required |
checksum
|
str | None
|
Content hash (skip computation if provided) |
None
|
tag_updated
|
bool
|
Touch the |
True
|
Returns:
| Type | Description |
|---|---|
str
|
checksum |
Source code in ftm_lakehouse/repository/archive.py
store_blob(uri, checksum=None)
Store bytes blob from given uri if it doesn't exist yet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
uri
|
Uri
|
Local or remote URI to the file |
required |
checksum
|
str | None
|
Content hash (skip computation if provided) |
None
|
Returns:
| Type | Description |
|---|---|
str
|
checksum |
Source code in ftm_lakehouse/repository/archive.py
stream(checksum)
write_blob(fh, checksum=None, check_exists=True)
Write a blob from the given open file-handler
Source code in ftm_lakehouse/repository/archive.py
EntityRepository
A dataset's entities and statements: writes go through the journal, reads and maintenance to the parquet store.
from ftmq.query import C, Query
from ftm_lakehouse import get_entities
entities = get_entities("my_dataset")
entities.add(entity, origin="import")
entities.writer(origin="import")
entities.flush()
entities.query(Query(C(origin="import")))
ftm_lakehouse.repository.EntityRepository
Bases: DatasetHandle
Entities and statements of a dataset: writes go to the journal, reads to
the parquet store, flush moves rows between them.
Example
Source code in ftm_lakehouse/repository/entities/main.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | |
statements
cached
property
The dataset's parquet store, built lazily; raises in api mode.
version
property
Current version of the main Delta table.
add(entity, origin=None, fragment=None, role=None)
Add a single entity to the journal.
Source code in ftm_lakehouse/repository/entities/main.py
add_many(entities, origin=None, fragment=None, role=None)
Add an entity iterator to the journal.
Source code in ftm_lakehouse/repository/entities/main.py
delete_entity(entity_id, origin=None)
Tombstone every statement of an entity, parquet and journal – one per
live row, carrying its fragment and role so it shadows that row.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
str
|
The entity to delete. |
required |
origin
|
str | None
|
Only delete its statements from this origin. |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of tombstones written. |
Source code in ftm_lakehouse/repository/entities/main.py
delete_origin(origin)
Physically drop an origin: flush, then
ParquetStore.delete_origin. Rows journalled
into it while this runs survive – stop the writers to be sure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
origin
|
str
|
The origin to drop. |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
RuntimeError
|
When the write fence cannot be acquired. |
Source code in ftm_lakehouse/repository/entities/main.py
delete_statement(stmt, fragment=None, role=None)
Tombstone one statement.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stmt
|
Statement
|
The statement – a |
required |
fragment
|
str | None
|
The row's fragment, for a plain |
None
|
role
|
str | None
|
The row's role, for a plain |
None
|
Source code in ftm_lakehouse/repository/entities/main.py
flush()
Drain the journal into the parquet store.
A concurrent flush makes this one a no-op, so 0 does not mean the
journal is empty.
Returns:
| Type | Description |
|---|---|
int
|
Number of statements appended. |
Source code in ftm_lakehouse/repository/entities/main.py
get(entity_id, flush_first=False)
Get a single entity by ID.
Source code in ftm_lakehouse/repository/entities/main.py
merge(force=False)
Flush, then merge the parquet store – force
rewrites clean partitions too.
Source code in ftm_lakehouse/repository/entities/main.py
query(q=None, *, flush_first=False)
Query entities from the parquet store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Query | None
|
Filters, plus ordering / slicing. |
None
|
flush_first
|
bool
|
Flush the journal first. |
False
|
Source code in ftm_lakehouse/repository/entities/main.py
query_statements(q=None, *, flush_first=False)
Query LakehouseStatement objects from the parquet store.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
q
|
Query | None
|
Filters, plus ordering / slicing. |
None
|
flush_first
|
bool
|
Flush the journal first. |
False
|
Source code in ftm_lakehouse/repository/entities/main.py
query_statements_data(q=None)
query_statements as plain dicts –
the stored columns, timestamps as ISO strings, as the api sends them.
Source code in ftm_lakehouse/repository/entities/main.py
shard(shards)
Flush, then shard the parquet store – the
storage half; ShardOperation
writes the new count to config.yml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shards
|
int
|
Target shard count; |
required |
Source code in ftm_lakehouse/repository/entities/main.py
stream()
Stream the exported entities.ftm.json – not the parquet store.
Source code in ftm_lakehouse/repository/entities/main.py
write_batches(tables)
Append JOURNAL_SCHEMA tables to parquet – the journal drain's write
loop. Each table is durable before the next is pulled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tables
|
Iterable[Table]
|
Stream of packed statement tables. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of rows written. |
Source code in ftm_lakehouse/repository/entities/main.py
write_stream(tables)
Append JOURNAL_SCHEMA tables to parquet as one file per partition –
the bulk imports' write
(write_stream).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tables
|
Iterable[Table]
|
Stream of packed statement tables. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Number of rows written. |
Source code in ftm_lakehouse/repository/entities/main.py
writer(origin=None, role=None)
A bulk journal writer – inserts its tail on success, drops it on error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
origin
|
str | None
|
Origin of the statements written through it. |
None
|
role
|
str | None
|
Who asserts them, for statements that carry no role. |
None
|
Source code in ftm_lakehouse/repository/entities/main.py
JobRepository
Job runs and their status, stored per job class – resolve the repository through the factory:
from ftm_lakehouse.operation.crawl import CrawlJob
from ftm_lakehouse.repository.factories import get_jobs
jobs = get_jobs("my_dataset", CrawlJob)
jobs.put(job)
jobs.get(run_id)
ftm_lakehouse.repository.JobRepository
Bases: DatasetHandle, Generic[J]
Repository for job run storage.
Persists job run data as JSON files, organized by job type and run ID.
Example
repo = JobRepository(dataset="my_data", uri="s3://bucket/dataset")
# Store a job run
repo.put(job)
# Get latest run for a job type
job = repo.latest(CrawlJob)
# Run a job with lifecycle management
with repo.run(job) as run:
# Do work...
run.save() # Periodic save
# Job automatically stopped when context exits
Source code in ftm_lakehouse/repository/job.py
delete(job)
get(run_id)
iterate()
latest()
Get the latest run for the configured job type (self.model).
Jobs are sorted by run ID (which contains timestamp), so the latest is the last in alphabetical order.
Source code in ftm_lakehouse/repository/job.py
put(job)
run(job)
Get a context manager for running a job.
The job is automatically started on entry and stopped on exit. If an exception occurs, it's recorded in the job's exc field.
Source code in ftm_lakehouse/repository/job.py
DocumentRepository
The read side of the exported document metadata (documents.csv, per origin scope).
ftm_lakehouse.repository.DocumentRepository
Bases: DatasetHandle
Repository for documents to consume for clients.
This gathers Document entities of the files stored in the archive and compiles a streamable csv list of document metadata.
Format: id,checksum,name,mimetype,path,size,updated_at,public_url
The csv itself is written by the export sweep
(ExportOperation),
which already holds every entity. The row shape and reading the result
back belong to
DocumentsArtifact;
this repository streams the written csv back.
Example
Source code in ftm_lakehouse/repository/documents.py
compression
property
Compression codec of the exported artifacts (the dataset's config).
csv_key(origin=None)
Store key of the exported documents csv, carrying the dataset's codec.
csv_uri(origin=None)
stream(origin=None)
ArtifactsRepository
The export artifacts of one dataset – statements.csv, entities.ftm.json, documents.csv (one per origin scope), parents.csv, statistics.json, index.json – and the diff series of the diffable ones.
from ftm_lakehouse.repository import get_artifacts
artifacts = get_artifacts("my_dataset")
artifacts.entities.exists()
artifacts.documents["crawl"].key
ftm_lakehouse.repository.ArtifactsRepository
Bases: DatasetHandle
The export artifacts of one dataset.
Example
Source code in ftm_lakehouse/repository/artifacts.py
resources()
Describe every written streamed artifact for index.json.
Source code in ftm_lakehouse/repository/artifacts.py
runs(now, parts)
One run per streamed artifact.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
now
|
datetime
|
When the export started – diff files are named after it. |
required |
parts
|
str
|
Directory the runs write their parts into. |
required |
Source code in ftm_lakehouse/repository/artifacts.py
streamed()
Every artifact the sweep writes – all but index.json – with one
documents scope per DOCUMENT_ORIGINS.
Source code in ftm_lakehouse/repository/artifacts.py
An artifact is a stateless declaration bound to a dataset; what is true only during an export – open writers, the diff window, counts – lives on its run, which ExportSession drives.
ftm_lakehouse.repository.artifacts.Artifact
One export artifact, bound to a dataset.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dataset
|
DatasetHandle
|
The dataset handle the artifact belongs to. |
required |
origin
|
str | None
|
Origin this variant is scoped to, |
None
|
Source code in ftm_lakehouse/repository/artifacts.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 | |
compression
property
The dataset's codec, or None where the artifact takes none.
key
property
The key the artifact actually lives at, codec included.
name
property
How this variant names itself in a result – crawl_documents.
tag
property
The codec-free key: what the freshness tag is named after.
uri
property
Full uri of the artifact in the dataset's store.
__getitem__(origin=None)
assembly()
This artifact's file, assembled from a run's parts – eager: a run that wrote nothing still replaces a stale file with an empty one.
Source code in ftm_lakehouse/repository/artifacts.py
exists()
make_resource(public_prefix=None)
Describe the artifact for index.json, or None if unwritten.
Source code in ftm_lakehouse/repository/artifacts.py
part(parts)
reader(mode='rb')
Open the artifact for reading, decoded with the dataset's codec.
Source code in ftm_lakehouse/repository/artifacts.py
run(now, parts)
touch(ts=None)
writer(parts=None, key=None)
A writer for the artifact (at key, its own by default), or for its
part of a run – lazy, so an unwritten part is never appended.
Source code in ftm_lakehouse/repository/artifacts.py
ftm_lakehouse.repository.artifacts.DiffableArtifact
Bases: Artifact
An artifact with a diff series: its files and its stored
{timestamp}:{version} state. The series directory carries no codec, so
it does not move when the dataset's compression does.
Source code in ftm_lakehouse/repository/artifacts.py
series
property
The directory this variant's diff files live in.
state_key
property
Tag key the {timestamp}:{version} state is stored under.
diff_assembly(ts)
This run's diff file, assembled like assembly – but lazy: a window
without changes leaves no file.
Source code in ftm_lakehouse/repository/artifacts.py
diff_part(parts)
diff_writer(parts)
A lazy writer for this series' part of a run's diff file.
Source code in ftm_lakehouse/repository/artifacts.py
get_state()
Last diff state as (timestamp, delta table version).
Source code in ftm_lakehouse/repository/artifacts.py
set_state(ts, version)
Store the diff state the next run is taken against.
ftm_lakehouse.repository.artifacts.DocumentsArtifact
Bases: DiffableArtifact
Document metadata and its diff series, scoped per origin.
Source code in ftm_lakehouse/repository/artifacts.py
is_document(data)
staticmethod
Whether an entity dict belongs in the documents export: a document
schema (is_document_schema) with a content hash.
Source code in ftm_lakehouse/repository/artifacts.py
is_document_schema(schema)
staticmethod
Whether the documents export carries schema: a Document
descendant other than Folder – shared by the live and delete paths.
Source code in ftm_lakehouse/repository/artifacts.py
is_parent_schema(schema)
staticmethod
Whether an entity of schema can be a document's parent folder.
make_document(data, public_prefix=None)
The row an entity dict contributes, path unset until the folder
tree is known.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
SDict
|
Entity dict, as |
required |
public_prefix
|
str | None
|
Public url prefix to build blob links against. |
None
|
Source code in ftm_lakehouse/repository/artifacts.py
stream()
Stream this variant's csv back as Document models.