lorebase-store 0.2.3__py3-none-any.whl
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.
- lorebase_store/__init__.py +1 -0
- lorebase_store/_migrations/env.py +106 -0
- lorebase_store/_migrations/script.py.mako +27 -0
- lorebase_store/_migrations/versions/0001_initial_schema.py +1071 -0
- lorebase_store/_migrations/versions/0002_merge_attempt_details.py +74 -0
- lorebase_store/_migrations/versions/0003_webhooks.py +127 -0
- lorebase_store/_migrations/versions/0004_defer_revision_references.py +38 -0
- lorebase_store/_migrations/versions/0005_security_definer_reads.py +396 -0
- lorebase_store/_migrations/versions/0006_api_key_usage.py +48 -0
- lorebase_store/_migrations/versions/0007_document_extraction.py +154 -0
- lorebase_store/_migrations/versions/0008_definer_argument_checks.py +178 -0
- lorebase_store/_migrations/versions/0009_api_key_networks.py +33 -0
- lorebase_store/_migrations/versions/0010_overlay_branches.py +582 -0
- lorebase_store/_migrations/versions/0011_branch_scoped_search_index.py +229 -0
- lorebase_store/_migrations/versions/0012_overlay_neighborhood_lookups.py +185 -0
- lorebase_store/_migrations/versions/0013_web_sessions.py +72 -0
- lorebase_store/_migrations/versions/0014_embedding_jobs.py +70 -0
- lorebase_store/_migrations/versions/0015_append_only_audit_log.py +83 -0
- lorebase_store/_migrations/versions/0016_sealed_webhook_keys.py +55 -0
- lorebase_store/_migrations/versions/0017_background_branch_copies.py +77 -0
- lorebase_store/_migrations/versions/0018_search_lexicon.py +477 -0
- lorebase_store/_migrations/versions/0019_vault_bindings.py +56 -0
- lorebase_store/_migrations/versions/0020_outbox_consumers.py +150 -0
- lorebase_store/_migrations/versions/0021_schema_suggestions.py +114 -0
- lorebase_store/_migrations/versions/0022_read_audit_and_shared_rate_limits.py +133 -0
- lorebase_store/_migrations/versions/0023_agent_trace.py +96 -0
- lorebase_store/_migrations/versions/0024_embedding_template_keys.py +205 -0
- lorebase_store/_migrations/versions/0025_snapshot_refs.py +35 -0
- lorebase_store/_migrations/versions/0026_plain_reverse_link_index.py +112 -0
- lorebase_store/_migrations/versions/0027_vault_rotation_and_tombstones.py +145 -0
- lorebase_store/_migrations/versions/0028_operation_deferred_events.py +71 -0
- lorebase_store/_migrations/versions/0029_agent_trace_sessions.py +108 -0
- lorebase_store/_migrations/versions/0030_path_fanout.py +31 -0
- lorebase_store/_migrations/versions/0031_branch_builds.py +91 -0
- lorebase_store/_migrations/versions/0032_lineage_revisions.py +35 -0
- lorebase_store/_migrations/versions/0033_vault_moved_tokens.py +30 -0
- lorebase_store/_migrations/versions/0034_inference_endpoint_modes.py +73 -0
- lorebase_store/_migrations/versions/0035_search_truncation.py +104 -0
- lorebase_store/_migrations/versions/0036_lineage_maps.py +325 -0
- lorebase_store/_migrations/versions/0037_bm25_search.py +346 -0
- lorebase_store/auth/__init__.py +52 -0
- lorebase_store/auth/api_keys.py +161 -0
- lorebase_store/auth/audit.py +382 -0
- lorebase_store/auth/checkpoints.py +185 -0
- lorebase_store/auth/grants.py +161 -0
- lorebase_store/auth/principals.py +158 -0
- lorebase_store/auth/scope.py +70 -0
- lorebase_store/auth/sessions.py +153 -0
- lorebase_store/auth/unit.py +53 -0
- lorebase_store/auth/usage.py +70 -0
- lorebase_store/blobs.py +73 -0
- lorebase_store/bm25.py +346 -0
- lorebase_store/bulk.py +147 -0
- lorebase_store/bundle.py +1830 -0
- lorebase_store/changefeed.py +261 -0
- lorebase_store/commit/__init__.py +42 -0
- lorebase_store/commit/changes.py +67 -0
- lorebase_store/commit/errors.py +60 -0
- lorebase_store/commit/migrations.py +335 -0
- lorebase_store/commit/pipeline.py +754 -0
- lorebase_store/commit/schema.py +123 -0
- lorebase_store/db.py +58 -0
- lorebase_store/definer.py +50 -0
- lorebase_store/digests.py +99 -0
- lorebase_store/embeddings.py +444 -0
- lorebase_store/endpoint_modes.py +59 -0
- lorebase_store/extraction/__init__.py +61 -0
- lorebase_store/extraction/items.py +187 -0
- lorebase_store/extraction/materialize.py +364 -0
- lorebase_store/extraction/proposal.py +65 -0
- lorebase_store/extraction/review.py +168 -0
- lorebase_store/gc.py +970 -0
- lorebase_store/indexes.py +1033 -0
- lorebase_store/jobs.py +651 -0
- lorebase_store/keyring.py +72 -0
- lorebase_store/layout.py +335 -0
- lorebase_store/materialize/__init__.py +103 -0
- lorebase_store/materialize/apply.py +436 -0
- lorebase_store/materialize/background.py +1184 -0
- lorebase_store/materialize/branch.py +268 -0
- lorebase_store/materialize/build.py +536 -0
- lorebase_store/materialize/derived.py +540 -0
- lorebase_store/materialize/lineage_backfill.py +502 -0
- lorebase_store/materialize/links.py +266 -0
- lorebase_store/materialize/overlay.py +292 -0
- lorebase_store/materialize/paths.py +315 -0
- lorebase_store/materialize/rebuild.py +326 -0
- lorebase_store/materialize/rows.py +153 -0
- lorebase_store/materialize/sensitivity.py +66 -0
- lorebase_store/materialize/snapshot.py +205 -0
- lorebase_store/materialize/stale.py +444 -0
- lorebase_store/materialize/verify.py +321 -0
- lorebase_store/merging/__init__.py +39 -0
- lorebase_store/merging/attempts.py +334 -0
- lorebase_store/merging/lineage.py +123 -0
- lorebase_store/merging/service.py +652 -0
- lorebase_store/migrations.py +133 -0
- lorebase_store/models/__init__.py +136 -0
- lorebase_store/models/base.py +64 -0
- lorebase_store/models/enums.py +132 -0
- lorebase_store/models/governance.py +268 -0
- lorebase_store/models/ingestion.py +288 -0
- lorebase_store/models/materialized.py +277 -0
- lorebase_store/models/proposals.py +195 -0
- lorebase_store/models/queues.py +87 -0
- lorebase_store/models/tracing.py +116 -0
- lorebase_store/models/versioning.py +222 -0
- lorebase_store/models/webhooks.py +96 -0
- lorebase_store/nodestore.py +384 -0
- lorebase_store/objectstore.py +162 -0
- lorebase_store/outbox_events.py +166 -0
- lorebase_store/profiling/__init__.py +58 -0
- lorebase_store/profiling/delimited.py +109 -0
- lorebase_store/profiling/postgres.py +211 -0
- lorebase_store/profiling/record_files.py +127 -0
- lorebase_store/profiling/records.py +92 -0
- lorebase_store/profiling/sql_databases.py +298 -0
- lorebase_store/ratelimit.py +129 -0
- lorebase_store/reads.py +1491 -0
- lorebase_store/replicas.py +434 -0
- lorebase_store/repositories/__init__.py +152 -0
- lorebase_store/repositories/changesets.py +59 -0
- lorebase_store/repositories/deferred_events.py +142 -0
- lorebase_store/repositories/documents.py +305 -0
- lorebase_store/repositories/domains.py +97 -0
- lorebase_store/repositories/events.py +205 -0
- lorebase_store/repositories/index_view.py +489 -0
- lorebase_store/repositories/invocations.py +68 -0
- lorebase_store/repositories/materializations.py +276 -0
- lorebase_store/repositories/materialized.py +1129 -0
- lorebase_store/repositories/merges.py +417 -0
- lorebase_store/repositories/proposal_items.py +199 -0
- lorebase_store/repositories/proposals.py +184 -0
- lorebase_store/repositories/provenance.py +77 -0
- lorebase_store/repositories/refs.py +452 -0
- lorebase_store/repositories/revisions.py +273 -0
- lorebase_store/repositories/scope.py +33 -0
- lorebase_store/repositories/source_runs.py +123 -0
- lorebase_store/repositories/suggestions.py +638 -0
- lorebase_store/runtime.py +87 -0
- lorebase_store/schema_cache.py +50 -0
- lorebase_store/settings.py +879 -0
- lorebase_store/storage.py +1478 -0
- lorebase_store/telemetry.py +142 -0
- lorebase_store/testing.py +108 -0
- lorebase_store/tracing.py +505 -0
- lorebase_store/traverse.py +578 -0
- lorebase_store/vault/__init__.py +50 -0
- lorebase_store/vault/keys.py +216 -0
- lorebase_store/vault/quotes.py +133 -0
- lorebase_store/vault/rotation.py +209 -0
- lorebase_store/vault/settings.py +152 -0
- lorebase_store/vault/store.py +987 -0
- lorebase_store/vault/transfer.py +558 -0
- lorebase_store/webhooks/__init__.py +24 -0
- lorebase_store/webhooks/delivery.py +637 -0
- lorebase_store/webhooks/keys.py +126 -0
- lorebase_store/webhooks/repository.py +142 -0
- lorebase_store/webhooks/settings.py +138 -0
- lorebase_store/webhooks/signing.py +50 -0
- lorebase_store-0.2.3.dist-info/METADATA +13 -0
- lorebase_store-0.2.3.dist-info/RECORD +163 -0
- lorebase_store-0.2.3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""Branch creation (design 6.5, 6.11 modes `full` and `overlay`).
|
|
2
|
+
|
|
3
|
+
Creating the ref is O(1). The source branch is locked meanwhile, so no commit moves it.
|
|
4
|
+
|
|
5
|
+
- `overlay`: the branch stores no rows yet and reads the source's rows as of its head
|
|
6
|
+
(`materialize.overlay`); only the compiled schema row is copied. Available when the
|
|
7
|
+
branch starts at the head of a fully materialized source that has fewer than
|
|
8
|
+
`store.materialize.overlay_max_per_branch` overlays; otherwise the branch is a copy.
|
|
9
|
+
- `copy`: the materialized head is copied from the source branch with `INSERT ... SELECT`
|
|
10
|
+
when the branch starts at the source head (an overlay source gives its resolved rows);
|
|
11
|
+
otherwise it is rebuilt from the tree of the start Revision. The branch then gets its
|
|
12
|
+
per-Attribute indexes. When an overlay is possible and the source holds more than
|
|
13
|
+
`store.materialize.async_copy_min_rows` rows, the branch is created as an overlay and a
|
|
14
|
+
`store.materialize` job copies its rows in batches (`materialize.background`):
|
|
15
|
+
`BranchCreation.pending` is then true. A copy of that size that cannot start as an
|
|
16
|
+
overlay (an overlay source, another start point, the overlay cap reached) is created
|
|
17
|
+
`building`: the same job writes its rows from the tree of its start Revision in batches
|
|
18
|
+
(`pending` too); meanwhile reads of its head are served from the tree and commits wait.
|
|
19
|
+
|
|
20
|
+
Without an explicit mode, `store.materialize.branch_mode` decides, except for names starting
|
|
21
|
+
with one of `overlay_branch_prefixes`, which default to overlays.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from collections.abc import Callable
|
|
27
|
+
from dataclasses import dataclass
|
|
28
|
+
from datetime import UTC, datetime
|
|
29
|
+
from enum import StrEnum
|
|
30
|
+
|
|
31
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
32
|
+
|
|
33
|
+
from lorebase_core.tree import PARTITION_SCHEMA
|
|
34
|
+
from lorebase_store.commit.schema import load_compiled
|
|
35
|
+
from lorebase_store.indexes import BranchIndexes
|
|
36
|
+
from lorebase_store.materialize.background import queue_build, queue_materialization
|
|
37
|
+
from lorebase_store.materialize.overlay import wants_overlay
|
|
38
|
+
from lorebase_store.materialize.rebuild import materialize_revision
|
|
39
|
+
from lorebase_store.materialize.stale import queue_if_stale
|
|
40
|
+
from lorebase_store.models.enums import Materialization, RefKind
|
|
41
|
+
from lorebase_store.nodestore import NodeRepository
|
|
42
|
+
from lorebase_store.repositories.domains import DomainRepository
|
|
43
|
+
from lorebase_store.repositories.materialized import MaterializedRepository
|
|
44
|
+
from lorebase_store.repositories.refs import RefRepository, RefRow
|
|
45
|
+
from lorebase_store.repositories.revisions import RevisionRepository, RevisionRow
|
|
46
|
+
from lorebase_store.repositories.scope import scope_to_domain
|
|
47
|
+
from lorebase_store.runtime import StoreRuntime, default_runtime
|
|
48
|
+
from lorebase_store.storage import constraints_only
|
|
49
|
+
|
|
50
|
+
BRANCH_CREATE_REASON = "branch.create"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class MaterializationMode(StrEnum):
|
|
54
|
+
"""How a new branch got its materialized head."""
|
|
55
|
+
|
|
56
|
+
COPY = "copy"
|
|
57
|
+
REBUILD = "rebuild"
|
|
58
|
+
OVERLAY = "overlay"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class BranchMode(StrEnum):
|
|
62
|
+
"""The materialization a caller asks for when creating a branch."""
|
|
63
|
+
|
|
64
|
+
COPY = "copy"
|
|
65
|
+
OVERLAY = "overlay"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class BranchExistsError(Exception):
|
|
69
|
+
"""A ref with that name already exists."""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class BranchDeletingError(Exception):
|
|
73
|
+
"""A branch with that name is being deleted in the background; the name is free again
|
|
74
|
+
once its rows are gone."""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass(frozen=True, slots=True)
|
|
78
|
+
class BranchCreation:
|
|
79
|
+
ref: RefRow
|
|
80
|
+
mode: MaterializationMode
|
|
81
|
+
pending: bool = False
|
|
82
|
+
"""A copy whose rows a background job is still copying (the ref is an overlay)."""
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
async def create_branch(
|
|
86
|
+
session: AsyncSession,
|
|
87
|
+
domain_id: str,
|
|
88
|
+
name: str,
|
|
89
|
+
*,
|
|
90
|
+
created_by: str,
|
|
91
|
+
source: str | None = None,
|
|
92
|
+
start: bytes | None = None,
|
|
93
|
+
mode: BranchMode | str | None = None,
|
|
94
|
+
runtime: StoreRuntime | None = None,
|
|
95
|
+
clock: Callable[[], datetime] | None = None,
|
|
96
|
+
) -> BranchCreation:
|
|
97
|
+
"""Create branch `name` at `start` (default: the head of `source`, itself defaulting to
|
|
98
|
+
the Domain's default branch), as an overlay or a full copy (`mode`, see module doc).
|
|
99
|
+
|
|
100
|
+
Runs in the caller's transaction when one is open, otherwise in its own.
|
|
101
|
+
"""
|
|
102
|
+
runtime = runtime or default_runtime()
|
|
103
|
+
now = clock or (lambda: datetime.now(UTC))
|
|
104
|
+
if mode is not None:
|
|
105
|
+
wanted = BranchMode(mode)
|
|
106
|
+
elif wants_overlay(name, runtime.settings.materialize):
|
|
107
|
+
wanted = BranchMode.OVERLAY
|
|
108
|
+
else:
|
|
109
|
+
wanted = BranchMode.COPY
|
|
110
|
+
args = (session, domain_id, name, created_by, source, start, wanted, runtime, now)
|
|
111
|
+
if session.in_transaction():
|
|
112
|
+
return await _create(*args)
|
|
113
|
+
async with session.begin():
|
|
114
|
+
return await _create(*args)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
async def _create(
|
|
118
|
+
session: AsyncSession,
|
|
119
|
+
domain_id: str,
|
|
120
|
+
name: str,
|
|
121
|
+
created_by: str,
|
|
122
|
+
source: str | None,
|
|
123
|
+
start: bytes | None,
|
|
124
|
+
wanted: BranchMode,
|
|
125
|
+
runtime: StoreRuntime,
|
|
126
|
+
now: Callable[[], datetime],
|
|
127
|
+
) -> BranchCreation:
|
|
128
|
+
await scope_to_domain(session, domain_id)
|
|
129
|
+
refs = RefRepository(session, domain_id)
|
|
130
|
+
if await refs.get(name) is not None:
|
|
131
|
+
raise BranchExistsError(f"ref {name!r} already exists in Domain {domain_id!r}")
|
|
132
|
+
if await refs.get_deleting(name) is not None:
|
|
133
|
+
raise BranchDeletingError(
|
|
134
|
+
f"branch {name!r} of Domain {domain_id!r} is being deleted; retry later"
|
|
135
|
+
)
|
|
136
|
+
source_name = source or (await DomainRepository(session).require(domain_id)).default_branch
|
|
137
|
+
await refs.lock(source_name, timeout_ms=runtime.settings.commit.lock_timeout_ms)
|
|
138
|
+
source_ref = await refs.require(source_name)
|
|
139
|
+
target = start or source_ref.head
|
|
140
|
+
head = await RevisionRepository(session, domain_id).require(target)
|
|
141
|
+
source_rows = MaterializedRepository(
|
|
142
|
+
session, domain_id, source_name, writes=runtime.settings.writes
|
|
143
|
+
)
|
|
144
|
+
# A source still being built has no complete rows to copy: its tree is read instead.
|
|
145
|
+
building = source_ref.materialization is Materialization.BUILDING
|
|
146
|
+
source_schema = None if building else await source_rows.schema()
|
|
147
|
+
at_head = source_ref.head == head.id and source_schema is not None
|
|
148
|
+
settings = runtime.settings.materialize
|
|
149
|
+
overlay_possible = (
|
|
150
|
+
at_head
|
|
151
|
+
and source_ref.kind is RefKind.BRANCH
|
|
152
|
+
and source_ref.materialization is Materialization.FULL
|
|
153
|
+
and len(await refs.overlays_of(source_name)) < settings.overlay_max_per_branch
|
|
154
|
+
)
|
|
155
|
+
background = (
|
|
156
|
+
wanted is BranchMode.COPY
|
|
157
|
+
and overlay_possible
|
|
158
|
+
and await source_rows.own_rows(limit=settings.async_copy_min_rows)
|
|
159
|
+
> settings.async_copy_min_rows
|
|
160
|
+
)
|
|
161
|
+
if (wanted is BranchMode.OVERLAY and overlay_possible) or background:
|
|
162
|
+
assert source_schema is not None
|
|
163
|
+
ref = await refs.create(
|
|
164
|
+
name,
|
|
165
|
+
head.id,
|
|
166
|
+
created_at=now(),
|
|
167
|
+
created_by=created_by,
|
|
168
|
+
kind=RefKind.BRANCH,
|
|
169
|
+
materialization=Materialization.OVERLAY,
|
|
170
|
+
reason=BRANCH_CREATE_REASON,
|
|
171
|
+
base_branch=source_name,
|
|
172
|
+
base_revision=head.id,
|
|
173
|
+
base_generation=head.generation,
|
|
174
|
+
)
|
|
175
|
+
await MaterializedRepository(
|
|
176
|
+
session, domain_id, name, writes=runtime.settings.writes, layout=ref.layout
|
|
177
|
+
).set_schema(source_schema)
|
|
178
|
+
# Queued: the overlay half of its reads uses them once the job worker built them.
|
|
179
|
+
await BranchIndexes(
|
|
180
|
+
session,
|
|
181
|
+
domain_id,
|
|
182
|
+
name,
|
|
183
|
+
settings=runtime.settings.indexes,
|
|
184
|
+
constraints_only=constraints_only(runtime.settings),
|
|
185
|
+
maintenance=runtime.index_maintenance,
|
|
186
|
+
).sync(load_compiled(source_schema.compiled))
|
|
187
|
+
# The overlay reads the source's rows: stale ones are the source's to rewrite (its
|
|
188
|
+
# job then queues the overlays based on it).
|
|
189
|
+
await queue_if_stale(
|
|
190
|
+
session, domain_id, source_name, load_compiled(source_schema.compiled), runtime=runtime
|
|
191
|
+
)
|
|
192
|
+
if background:
|
|
193
|
+
await queue_materialization(session, domain_id, ref, at=now())
|
|
194
|
+
return BranchCreation(ref, MaterializationMode.COPY, pending=True)
|
|
195
|
+
return BranchCreation(ref, MaterializationMode.OVERLAY)
|
|
196
|
+
if await _large_copy(session, domain_id, source_rows, head, at_head=at_head, runtime=runtime):
|
|
197
|
+
ref = await refs.create(
|
|
198
|
+
name,
|
|
199
|
+
head.id,
|
|
200
|
+
created_at=now(),
|
|
201
|
+
created_by=created_by,
|
|
202
|
+
kind=RefKind.BRANCH,
|
|
203
|
+
materialization=Materialization.BUILDING,
|
|
204
|
+
reason=BRANCH_CREATE_REASON,
|
|
205
|
+
)
|
|
206
|
+
await queue_build(session, domain_id, name, source=source_name, head=head, at=now())
|
|
207
|
+
mode = MaterializationMode.COPY if at_head else MaterializationMode.REBUILD
|
|
208
|
+
return BranchCreation(ref, mode, pending=True)
|
|
209
|
+
ref = await refs.create(
|
|
210
|
+
name,
|
|
211
|
+
head.id,
|
|
212
|
+
created_at=now(),
|
|
213
|
+
created_by=created_by,
|
|
214
|
+
kind=RefKind.BRANCH,
|
|
215
|
+
materialization=Materialization.FULL,
|
|
216
|
+
reason=BRANCH_CREATE_REASON,
|
|
217
|
+
)
|
|
218
|
+
repository = MaterializedRepository(
|
|
219
|
+
session, domain_id, name, writes=runtime.settings.writes, layout=ref.layout
|
|
220
|
+
)
|
|
221
|
+
if at_head:
|
|
222
|
+
assert source_schema is not None
|
|
223
|
+
await repository.copy_from(source_name)
|
|
224
|
+
copied = load_compiled(source_schema.compiled)
|
|
225
|
+
await BranchIndexes(
|
|
226
|
+
session,
|
|
227
|
+
domain_id,
|
|
228
|
+
name,
|
|
229
|
+
settings=runtime.settings.indexes,
|
|
230
|
+
constraints_only=constraints_only(runtime.settings),
|
|
231
|
+
maintenance=runtime.index_maintenance,
|
|
232
|
+
).sync(copied)
|
|
233
|
+
# Stale rows of the source are copied as they are.
|
|
234
|
+
await queue_if_stale(session, domain_id, name, copied, runtime=runtime)
|
|
235
|
+
return BranchCreation(ref, MaterializationMode.COPY)
|
|
236
|
+
await materialize_revision(session, domain_id, name, head, runtime=runtime)
|
|
237
|
+
return BranchCreation(ref, MaterializationMode.REBUILD)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
async def _large_copy(
|
|
241
|
+
session: AsyncSession,
|
|
242
|
+
domain_id: str,
|
|
243
|
+
source_rows: MaterializedRepository,
|
|
244
|
+
head: RevisionRow,
|
|
245
|
+
*,
|
|
246
|
+
at_head: bool,
|
|
247
|
+
runtime: StoreRuntime,
|
|
248
|
+
) -> bool:
|
|
249
|
+
"""Whether a copy that cannot start as an overlay holds more than
|
|
250
|
+
`async_copy_min_rows` rows: the rows the source reads at its head (an overlay's own rows
|
|
251
|
+
and its base's, an upper bound), or the entries of the start Revision's tree."""
|
|
252
|
+
limit = runtime.settings.materialize.async_copy_min_rows
|
|
253
|
+
if at_head:
|
|
254
|
+
layout = await source_rows.layout()
|
|
255
|
+
total = await source_rows.own_rows(limit=limit)
|
|
256
|
+
if layout.base is not None and total <= limit:
|
|
257
|
+
base_rows = MaterializedRepository(
|
|
258
|
+
session, domain_id, layout.base, writes=runtime.settings.writes
|
|
259
|
+
)
|
|
260
|
+
total += await base_rows.own_rows(limit=limit)
|
|
261
|
+
return total > limit
|
|
262
|
+
settings = runtime.settings
|
|
263
|
+
nodes = NodeRepository(
|
|
264
|
+
session, domain_id, writes=settings.writes, batch=settings.nodes.prefetch_batch
|
|
265
|
+
)
|
|
266
|
+
tree = await nodes.load_tree(head.root)
|
|
267
|
+
total = sum(ref.count for name, ref in tree.partitions.items() if name != PARTITION_SCHEMA)
|
|
268
|
+
return total > limit
|