@hearthlog/runtime 0.0.0-stage → 0.1.0
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/LICENSE +235 -0
- package/package.json +51 -3
- package/src/access/session.ts +223 -0
- package/src/access/user-session.ts +61 -0
- package/src/ai/decisions.ts +89 -0
- package/src/calendar/draft.ts +84 -0
- package/src/calendar/feeds.ts +91 -0
- package/src/calendar/groups.ts +198 -0
- package/src/calendar/logic.ts +141 -0
- package/src/calendar/preferences.ts +40 -0
- package/src/calendar/weeks.ts +56 -0
- package/src/commands/index.ts +184 -0
- package/src/commands/local-commit.ts +214 -0
- package/src/commands/standard.ts +8 -0
- package/src/commands/validation.ts +206 -0
- package/src/db/bootstrap.ts +72 -0
- package/src/db/calendar.ts +638 -0
- package/src/db/dynamic-ddl.ts +127 -0
- package/src/db/entities.ts +208 -0
- package/src/db/history.ts +194 -0
- package/src/db/index.ts +1240 -0
- package/src/db/kv.ts +33 -0
- package/src/db/local-statistics.ts +106 -0
- package/src/db/module-projections.ts +46 -0
- package/src/db/raw-browser.ts +361 -0
- package/src/db/read-repositories.ts +29 -0
- package/src/db/read-session.ts +47 -0
- package/src/db/schema-version.ts +76 -0
- package/src/db/session-context.ts +33 -0
- package/src/event/code-export.ts +65 -0
- package/src/event/dynamic-entities.ts +503 -0
- package/src/event/dynamic-materializer.ts +288 -0
- package/src/event/handlers.ts +490 -0
- package/src/event/index.ts +53 -0
- package/src/event/meta-entity-types.ts +165 -0
- package/src/event/projection-builder.ts +384 -0
- package/src/event/queries.ts +126 -0
- package/src/event/rebuild.ts +176 -0
- package/src/event/reference-lookup.ts +93 -0
- package/src/event/registry.ts +158 -0
- package/src/event/schema-effects.ts +45 -0
- package/src/event/types.ts +20 -0
- package/src/history/action-boundary.ts +18 -0
- package/src/history/action-detail.ts +23 -0
- package/src/history/change-comparison.ts +29 -0
- package/src/history/change-display.ts +41 -0
- package/src/history/contracts.ts +63 -0
- package/src/history/history.ts +372 -0
- package/src/history/legacy-replay.ts +69 -0
- package/src/history/legacy-url.ts +9 -0
- package/src/history/lineage.ts +123 -0
- package/src/history/log-format.ts +17 -0
- package/src/history/log-map.ts +110 -0
- package/src/history/navigation.ts +14 -0
- package/src/history/point-snapshot.ts +229 -0
- package/src/history/timeline.ts +215 -0
- package/src/history/url.ts +18 -0
- package/src/ledger/README.md +118 -0
- package/src/ledger/admin-client.ts +616 -0
- package/src/ledger/client.ts +10 -0
- package/src/ledger/config.ts +117 -0
- package/src/ledger/entity-id.ts +115 -0
- package/src/ledger/errors.ts +144 -0
- package/src/ledger/http-client.ts +590 -0
- package/src/ledger/index.ts +67 -0
- package/src/ledger/socket.ts +400 -0
- package/src/ledger/types.ts +202 -0
- package/src/ledger/version-tracker-singleton.ts +12 -0
- package/src/ledger/version-tracker.ts +259 -0
- package/src/log-management.ts +123 -0
- package/src/log-validation.ts +19 -0
- package/src/native/reminders.ts +2 -0
- package/src/native/shell.svelte.ts +136 -0
- package/src/native/shell.ts +102 -0
- package/src/pwa/registration.ts +169 -0
- package/src/recovery/local-recovery.ts +59 -0
- package/src/recovery/reset-sequence.ts +13 -0
- package/src/runtime/clock.ts +43 -0
- package/src/runtime/kept-page-data.svelte.ts +42 -0
- package/src/runtime/page-data.svelte.ts +160 -0
- package/src/runtime/phone-header.svelte.ts +17 -0
- package/src/runtime/read-coordinator.ts +103 -0
- package/src/runtime/refresh.ts +15 -0
- package/src/runtime/start-page.ts +56 -0
- package/src/runtime/view.ts +83 -0
- package/src/runtime/workspace.ts +62 -0
- package/src/storage/indexeddb-statistics.ts +153 -0
- package/src/store/attention.svelte.ts +51 -0
- package/src/store/conflict-merge.ts +169 -0
- package/src/store/entity-sync-state.svelte.ts +36 -0
- package/src/store/event-log.svelte.ts +109 -0
- package/src/store/events.svelte.ts +14 -0
- package/src/store/local-context.ts +93 -0
- package/src/store/local-store.svelte.ts +58 -0
- package/src/store/log-version.svelte.ts +35 -0
- package/src/store/logs.svelte.ts +60 -0
- package/src/store/moved.svelte.ts +43 -0
- package/src/store/offline-readiness.svelte.ts +188 -0
- package/src/store/outbox-request.ts +61 -0
- package/src/store/outbox.ts +426 -0
- package/src/store/pending-work-transfer.ts +49 -0
- package/src/store/pending-work.ts +143 -0
- package/src/store/sync-coordinator.ts +170 -0
- package/src/store/sync-invalidation.ts +10 -0
- package/src/store/sync-issues.ts +406 -0
- package/src/store/sync-progress.ts +54 -0
- package/src/store/sync-state.ts +127 -0
- package/src/store/sync.svelte.ts +1010 -0
- package/src/store/tab-coordination.ts +164 -0
- package/src/testing/e2e-seed.ts +40 -0
- package/src/testing/local-database.ts +120 -0
- package/src/testing/projection-database.ts +105 -0
- package/src/testing/test-entities.ts +28 -0
- package/src/theme/appearance.svelte.ts +111 -0
- package/src/utils/address.ts +5 -0
- package/src/utils/async.ts +30 -0
- package/src/utils/long-press.ts +70 -0
- package/src/utils/perf-dataset.ts +405 -0
- package/src/utils/perf.ts +627 -0
- package/README.md +0 -3
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import { requireActiveContext, setActiveContext } from '../db/index.js';
|
|
2
|
+
import { set as setKv } from '../db/kv.js';
|
|
3
|
+
import { handleIncomingStoredEvents, replaceAllStoredEvents } from '../event/index.js';
|
|
4
|
+
import type { DynamicFieldDefinition } from '../event/meta-entity-types.js';
|
|
5
|
+
import type { StoredEvent } from '../ledger/types.js';
|
|
6
|
+
import { notifyEventsChanged } from '../store/events.svelte.js';
|
|
7
|
+
import {
|
|
8
|
+
addSyncLogEntry,
|
|
9
|
+
stopRealtime,
|
|
10
|
+
} from '../store/sync.svelte.js';
|
|
11
|
+
|
|
12
|
+
export const PERFORMANCE_DATASET_LOG_ID = 'perf-benchmark-local';
|
|
13
|
+
|
|
14
|
+
export interface PerformanceDatasetConfig {
|
|
15
|
+
vendorCount: number;
|
|
16
|
+
categoryCount: number;
|
|
17
|
+
itemCount: number;
|
|
18
|
+
updateCount: number;
|
|
19
|
+
replayCount: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PerformanceDatasetManifest {
|
|
23
|
+
config: PerformanceDatasetConfig;
|
|
24
|
+
entityTypeCount: number;
|
|
25
|
+
dynamicEntityCount: number;
|
|
26
|
+
seedEventCount: number;
|
|
27
|
+
replayEventCount: number;
|
|
28
|
+
seedHeadVersion: number;
|
|
29
|
+
replayHeadVersion: number;
|
|
30
|
+
referenceFieldCount: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface PerformanceDataset {
|
|
34
|
+
manifest: PerformanceDatasetManifest;
|
|
35
|
+
seedEvents: StoredEvent[];
|
|
36
|
+
replayEvents: StoredEvent[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const ENTITY_NAMES = {
|
|
40
|
+
vendor: 'perf_vendor',
|
|
41
|
+
category: 'perf_category',
|
|
42
|
+
item: 'perf_item',
|
|
43
|
+
} as const;
|
|
44
|
+
|
|
45
|
+
export const DEFAULT_PERFORMANCE_DATASET_CONFIG: PerformanceDatasetConfig = {
|
|
46
|
+
vendorCount: 40,
|
|
47
|
+
categoryCount: 120,
|
|
48
|
+
itemCount: 1200,
|
|
49
|
+
updateCount: 320,
|
|
50
|
+
replayCount: 250,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function assertPositiveInteger(value: number, label: string): void {
|
|
54
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
55
|
+
throw new Error(`${label} must be a positive integer`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function validateConfig(config: PerformanceDatasetConfig): void {
|
|
60
|
+
assertPositiveInteger(config.vendorCount, 'vendorCount');
|
|
61
|
+
assertPositiveInteger(config.categoryCount, 'categoryCount');
|
|
62
|
+
assertPositiveInteger(config.itemCount, 'itemCount');
|
|
63
|
+
assertPositiveInteger(config.updateCount, 'updateCount');
|
|
64
|
+
assertPositiveInteger(config.replayCount, 'replayCount');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function padIndex(index: number): string {
|
|
68
|
+
return String(index).padStart(4, '0');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function createId(kind: string, index: number): string {
|
|
72
|
+
return `perf-${kind}-${padIndex(index)}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function createEntityId(entityName: string, id: string): string {
|
|
76
|
+
return `${entityName}:${id}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function createEntityTypeFields(
|
|
80
|
+
entityName:
|
|
81
|
+
| typeof ENTITY_NAMES.vendor
|
|
82
|
+
| typeof ENTITY_NAMES.category
|
|
83
|
+
| typeof ENTITY_NAMES.item
|
|
84
|
+
): DynamicFieldDefinition[] {
|
|
85
|
+
if (entityName === ENTITY_NAMES.vendor) {
|
|
86
|
+
return [
|
|
87
|
+
{ name: 'name', type: 'string', payloadKey: 'name', required: true },
|
|
88
|
+
{ name: 'tier', type: 'string', payloadKey: 'tier', required: true },
|
|
89
|
+
{ name: 'rating', type: 'number', payloadKey: 'rating', required: true },
|
|
90
|
+
{ name: 'is_preferred', type: 'boolean', payloadKey: 'isPreferred', default: false },
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (entityName === ENTITY_NAMES.category) {
|
|
95
|
+
return [
|
|
96
|
+
{ name: 'name', type: 'string', payloadKey: 'name', required: true },
|
|
97
|
+
{ name: 'group_code', type: 'string', payloadKey: 'groupCode', required: true },
|
|
98
|
+
{ name: 'sort_order', type: 'number', payloadKey: 'sortOrder', required: true },
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return [
|
|
103
|
+
{ name: 'name', type: 'string', payloadKey: 'name', required: true },
|
|
104
|
+
{ name: 'sku', type: 'string', payloadKey: 'sku', required: true },
|
|
105
|
+
{ name: 'status', type: 'string', payloadKey: 'status', required: true },
|
|
106
|
+
{ name: 'amount', type: 'number', payloadKey: 'amount', required: true },
|
|
107
|
+
{ name: 'score', type: 'number', payloadKey: 'score', required: true },
|
|
108
|
+
{
|
|
109
|
+
name: 'vendor_id',
|
|
110
|
+
type: 'reference',
|
|
111
|
+
payloadKey: 'vendorId',
|
|
112
|
+
required: true,
|
|
113
|
+
referenceTo: ENTITY_NAMES.vendor,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'backup_vendor_id',
|
|
117
|
+
type: 'reference',
|
|
118
|
+
payloadKey: 'backupVendorId',
|
|
119
|
+
required: true,
|
|
120
|
+
referenceTo: ENTITY_NAMES.vendor,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: 'category_id',
|
|
124
|
+
type: 'reference',
|
|
125
|
+
payloadKey: 'categoryId',
|
|
126
|
+
required: true,
|
|
127
|
+
referenceTo: ENTITY_NAMES.category,
|
|
128
|
+
},
|
|
129
|
+
{ name: 'captured_at', type: 'datetime', payloadKey: 'capturedAt', required: true },
|
|
130
|
+
{ name: 'is_active', type: 'boolean', payloadKey: 'isActive', default: true },
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function buildEntityTypeDefinitionEvents(): Array<{
|
|
135
|
+
entityName: string;
|
|
136
|
+
typeId: string;
|
|
137
|
+
fields: DynamicFieldDefinition[];
|
|
138
|
+
}> {
|
|
139
|
+
return [
|
|
140
|
+
{
|
|
141
|
+
entityName: ENTITY_NAMES.vendor,
|
|
142
|
+
typeId: createId('entity-type-vendor', 1),
|
|
143
|
+
fields: createEntityTypeFields(ENTITY_NAMES.vendor),
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
entityName: ENTITY_NAMES.category,
|
|
147
|
+
typeId: createId('entity-type-category', 1),
|
|
148
|
+
fields: createEntityTypeFields(ENTITY_NAMES.category),
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
entityName: ENTITY_NAMES.item,
|
|
152
|
+
typeId: createId('entity-type-item', 1),
|
|
153
|
+
fields: createEntityTypeFields(ENTITY_NAMES.item),
|
|
154
|
+
},
|
|
155
|
+
];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function pushStoredEvent(
|
|
159
|
+
events: StoredEvent[],
|
|
160
|
+
options: {
|
|
161
|
+
version: number;
|
|
162
|
+
entityVersion: number;
|
|
163
|
+
type: string;
|
|
164
|
+
entityId: string;
|
|
165
|
+
timestamp: number;
|
|
166
|
+
payload: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
): void {
|
|
169
|
+
events.push({
|
|
170
|
+
version: options.version,
|
|
171
|
+
id: `perf-event-${String(options.version).padStart(6, '0')}`,
|
|
172
|
+
type: options.type,
|
|
173
|
+
entityId: options.entityId,
|
|
174
|
+
entityVersion: options.entityVersion,
|
|
175
|
+
timestamp: options.timestamp,
|
|
176
|
+
payload: options.payload,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function buildPerformanceDataset(
|
|
181
|
+
config: PerformanceDatasetConfig = DEFAULT_PERFORMANCE_DATASET_CONFIG
|
|
182
|
+
): PerformanceDataset {
|
|
183
|
+
validateConfig(config);
|
|
184
|
+
|
|
185
|
+
const seedEvents: StoredEvent[] = [];
|
|
186
|
+
const replayEvents: StoredEvent[] = [];
|
|
187
|
+
const entityVersions = new Map<string, number>();
|
|
188
|
+
const vendorIds = Array.from({ length: config.vendorCount }, (_, index) =>
|
|
189
|
+
createId('vendor', index + 1)
|
|
190
|
+
);
|
|
191
|
+
const categoryIds = Array.from({ length: config.categoryCount }, (_, index) =>
|
|
192
|
+
createId('category', index + 1)
|
|
193
|
+
);
|
|
194
|
+
const itemIds = Array.from({ length: config.itemCount }, (_, index) =>
|
|
195
|
+
createId('item', index + 1)
|
|
196
|
+
);
|
|
197
|
+
const entityTypeDefinitions = buildEntityTypeDefinitionEvents();
|
|
198
|
+
|
|
199
|
+
let version = 1;
|
|
200
|
+
const baseTimestamp = Date.UTC(2026, 2, 11, 12, 0, 0);
|
|
201
|
+
|
|
202
|
+
for (const [index, definition] of entityTypeDefinitions.entries()) {
|
|
203
|
+
pushStoredEvent(seedEvents, {
|
|
204
|
+
version,
|
|
205
|
+
entityVersion: 1,
|
|
206
|
+
type: 'ENTITY_TYPE_DEFINED',
|
|
207
|
+
entityId: `entity_type:${definition.typeId}`,
|
|
208
|
+
timestamp: baseTimestamp + index,
|
|
209
|
+
payload: {
|
|
210
|
+
id: definition.typeId,
|
|
211
|
+
name: definition.entityName,
|
|
212
|
+
displayName: definition.entityName
|
|
213
|
+
.split('_')
|
|
214
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
215
|
+
.join(' '),
|
|
216
|
+
tableName: `${definition.entityName}s`,
|
|
217
|
+
fields: definition.fields,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
version += 1;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
for (const [index, vendorId] of vendorIds.entries()) {
|
|
224
|
+
const entityId = createEntityId(ENTITY_NAMES.vendor, vendorId);
|
|
225
|
+
entityVersions.set(entityId, 1);
|
|
226
|
+
pushStoredEvent(seedEvents, {
|
|
227
|
+
version,
|
|
228
|
+
entityVersion: 1,
|
|
229
|
+
type: 'PERF_VENDOR_ADDED',
|
|
230
|
+
entityId,
|
|
231
|
+
timestamp: baseTimestamp + version,
|
|
232
|
+
payload: {
|
|
233
|
+
id: vendorId,
|
|
234
|
+
name: `Vendor ${index + 1}`,
|
|
235
|
+
tier: ['bronze', 'silver', 'gold'][index % 3],
|
|
236
|
+
rating: Number((3.2 + ((index % 15) * 0.1)).toFixed(1)),
|
|
237
|
+
isPreferred: index % 5 === 0,
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
version += 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
for (const [index, categoryId] of categoryIds.entries()) {
|
|
244
|
+
const entityId = createEntityId(ENTITY_NAMES.category, categoryId);
|
|
245
|
+
entityVersions.set(entityId, 1);
|
|
246
|
+
pushStoredEvent(seedEvents, {
|
|
247
|
+
version,
|
|
248
|
+
entityVersion: 1,
|
|
249
|
+
type: 'PERF_CATEGORY_ADDED',
|
|
250
|
+
entityId,
|
|
251
|
+
timestamp: baseTimestamp + version,
|
|
252
|
+
payload: {
|
|
253
|
+
id: categoryId,
|
|
254
|
+
name: `Category ${index + 1}`,
|
|
255
|
+
groupCode: `G-${String((index % 12) + 1).padStart(2, '0')}`,
|
|
256
|
+
sortOrder: index + 1,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
version += 1;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
for (const [index, itemId] of itemIds.entries()) {
|
|
263
|
+
const entityId = createEntityId(ENTITY_NAMES.item, itemId);
|
|
264
|
+
const vendorId = vendorIds[index % vendorIds.length];
|
|
265
|
+
const backupVendorId =
|
|
266
|
+
vendorIds[(index + 7) % vendorIds.length];
|
|
267
|
+
const categoryId = categoryIds[index % categoryIds.length];
|
|
268
|
+
|
|
269
|
+
entityVersions.set(entityId, 1);
|
|
270
|
+
pushStoredEvent(seedEvents, {
|
|
271
|
+
version,
|
|
272
|
+
entityVersion: 1,
|
|
273
|
+
type: 'PERF_ITEM_ADDED',
|
|
274
|
+
entityId,
|
|
275
|
+
timestamp: baseTimestamp + version,
|
|
276
|
+
payload: {
|
|
277
|
+
id: itemId,
|
|
278
|
+
name: `Benchmark Item ${index + 1}`,
|
|
279
|
+
sku: `SKU-${String(index + 1).padStart(5, '0')}`,
|
|
280
|
+
status: ['draft', 'active', 'review'][index % 3],
|
|
281
|
+
amount: 100 + (index % 50) * 17,
|
|
282
|
+
score: Number((50 + (index % 300) * 0.25).toFixed(2)),
|
|
283
|
+
vendorId,
|
|
284
|
+
backupVendorId,
|
|
285
|
+
categoryId,
|
|
286
|
+
capturedAt: new Date(baseTimestamp + index * 60_000).toISOString(),
|
|
287
|
+
isActive: index % 17 !== 0,
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
version += 1;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
for (let index = 0; index < config.updateCount; index += 1) {
|
|
294
|
+
const itemId = itemIds[index % itemIds.length];
|
|
295
|
+
const entityId = createEntityId(ENTITY_NAMES.item, itemId);
|
|
296
|
+
const entityVersion = (entityVersions.get(entityId) ?? 1) + 1;
|
|
297
|
+
entityVersions.set(entityId, entityVersion);
|
|
298
|
+
|
|
299
|
+
pushStoredEvent(seedEvents, {
|
|
300
|
+
version,
|
|
301
|
+
entityVersion,
|
|
302
|
+
type: 'PERF_ITEM_UPDATED',
|
|
303
|
+
entityId,
|
|
304
|
+
timestamp: baseTimestamp + version,
|
|
305
|
+
payload: {
|
|
306
|
+
id: itemId,
|
|
307
|
+
status: ['active', 'review', 'archived'][index % 3],
|
|
308
|
+
amount: 250 + (index % 60) * 23,
|
|
309
|
+
score: Number((60 + (index % 200) * 0.37).toFixed(2)),
|
|
310
|
+
backupVendorId: vendorIds[(index + 11) % vendorIds.length],
|
|
311
|
+
capturedAt: new Date(baseTimestamp + (index + 10_000) * 30_000).toISOString(),
|
|
312
|
+
isActive: index % 9 !== 0,
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
version += 1;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const seedHeadVersion = version - 1;
|
|
319
|
+
|
|
320
|
+
for (let index = 0; index < config.replayCount; index += 1) {
|
|
321
|
+
const itemId = itemIds[(index * 7) % itemIds.length];
|
|
322
|
+
const entityId = createEntityId(ENTITY_NAMES.item, itemId);
|
|
323
|
+
const entityVersion = (entityVersions.get(entityId) ?? 1) + 1;
|
|
324
|
+
entityVersions.set(entityId, entityVersion);
|
|
325
|
+
|
|
326
|
+
pushStoredEvent(replayEvents, {
|
|
327
|
+
version,
|
|
328
|
+
entityVersion,
|
|
329
|
+
type: 'PERF_ITEM_UPDATED',
|
|
330
|
+
entityId,
|
|
331
|
+
timestamp: baseTimestamp + version,
|
|
332
|
+
payload: {
|
|
333
|
+
id: itemId,
|
|
334
|
+
status: ['review', 'active', 'archived', 'active'][index % 4],
|
|
335
|
+
amount: 400 + (index % 75) * 19,
|
|
336
|
+
score: Number((80 + (index % 250) * 0.19).toFixed(2)),
|
|
337
|
+
vendorId: vendorIds[(index + 3) % vendorIds.length],
|
|
338
|
+
backupVendorId: vendorIds[(index + 17) % vendorIds.length],
|
|
339
|
+
categoryId: categoryIds[(index + 5) % categoryIds.length],
|
|
340
|
+
capturedAt: new Date(baseTimestamp + (index + 20_000) * 15_000).toISOString(),
|
|
341
|
+
isActive: index % 13 !== 0,
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
version += 1;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const manifest: PerformanceDatasetManifest = {
|
|
348
|
+
config: { ...config },
|
|
349
|
+
entityTypeCount: entityTypeDefinitions.length,
|
|
350
|
+
dynamicEntityCount:
|
|
351
|
+
config.vendorCount + config.categoryCount + config.itemCount,
|
|
352
|
+
seedEventCount: seedEvents.length,
|
|
353
|
+
replayEventCount: replayEvents.length,
|
|
354
|
+
seedHeadVersion,
|
|
355
|
+
replayHeadVersion: version - 1,
|
|
356
|
+
referenceFieldCount: 3,
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
manifest,
|
|
361
|
+
seedEvents,
|
|
362
|
+
replayEvents,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export async function loadPerformanceDataset(
|
|
367
|
+
config: PerformanceDatasetConfig = DEFAULT_PERFORMANCE_DATASET_CONFIG
|
|
368
|
+
): Promise<PerformanceDatasetManifest> {
|
|
369
|
+
const dataset = buildPerformanceDataset(config);
|
|
370
|
+
await stopRealtime();
|
|
371
|
+
const context = await requireActiveContext();
|
|
372
|
+
// setActiveContext updates this tab's session + last-used defaults
|
|
373
|
+
await setActiveContext({ ...context, logId: PERFORMANCE_DATASET_LOG_ID });
|
|
374
|
+
await replaceAllStoredEvents(dataset.seedEvents);
|
|
375
|
+
await setKv('db-log-id', PERFORMANCE_DATASET_LOG_ID);
|
|
376
|
+
await setKv('log-head-version', dataset.manifest.seedHeadVersion);
|
|
377
|
+
notifyEventsChanged();
|
|
378
|
+
await addSyncLogEntry(
|
|
379
|
+
'download',
|
|
380
|
+
'Loaded local performance benchmark dataset',
|
|
381
|
+
`${dataset.manifest.seedEventCount} stored events`
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
return dataset.manifest;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export async function replayPerformanceDataset(
|
|
388
|
+
config: PerformanceDatasetConfig = DEFAULT_PERFORMANCE_DATASET_CONFIG
|
|
389
|
+
): Promise<PerformanceDatasetManifest> {
|
|
390
|
+
const dataset = buildPerformanceDataset(config);
|
|
391
|
+
await stopRealtime();
|
|
392
|
+
const context = await requireActiveContext();
|
|
393
|
+
await setActiveContext({ ...context, logId: PERFORMANCE_DATASET_LOG_ID });
|
|
394
|
+
await handleIncomingStoredEvents(dataset.replayEvents);
|
|
395
|
+
await setKv('db-log-id', PERFORMANCE_DATASET_LOG_ID);
|
|
396
|
+
await setKv('log-head-version', dataset.manifest.replayHeadVersion);
|
|
397
|
+
notifyEventsChanged();
|
|
398
|
+
await addSyncLogEntry(
|
|
399
|
+
'download',
|
|
400
|
+
'Replayed local performance sync burst',
|
|
401
|
+
`${dataset.manifest.replayEventCount} stored events`
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
return dataset.manifest;
|
|
405
|
+
}
|