@bldrs-ai/conway 1.536.1507 → 1.543.1513
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/compiled/examples/browser-bundled.cjs +39 -5
- package/compiled/examples/cli-bundled.cjs +197 -22
- package/compiled/examples/cli-step-bundled.cjs +39 -5
- package/compiled/examples/validator-bundled.cjs +39 -5
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.d.ts +2 -0
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.d.ts.map +1 -0
- package/compiled/src/compat/web-ifc/geometry_shard_coordination.test.js +236 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts +26 -0
- package/compiled/src/compat/web-ifc/ifc_api.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api.js +33 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts +6 -0
- package/compiled/src/compat/web-ifc/ifc_api_model_passthrough.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_preview_channel.test.js +264 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts +116 -5
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/ifc_api_proxy_ifc.js +256 -85
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts +79 -0
- package/compiled/src/compat/web-ifc/store_preview_channel.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/store_preview_channel.js +237 -14
- package/compiled/src/compat/web-ifc/store_preview_channel.test.js +270 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts +106 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.d.ts.map +1 -1
- package/compiled/src/compat/web-ifc/streamed_preview_channel.js +269 -17
- package/compiled/src/core/progress_log.d.ts +75 -2
- package/compiled/src/core/progress_log.d.ts.map +1 -1
- package/compiled/src/core/progress_log.js +59 -2
- package/compiled/src/core/progress_log.test.js +75 -1
- package/compiled/src/ifc/dangling_placement_error.d.ts +35 -0
- package/compiled/src/ifc/dangling_placement_error.d.ts.map +1 -0
- package/compiled/src/ifc/dangling_placement_error.js +38 -0
- package/compiled/src/ifc/geometry_dispatch.d.ts +74 -3
- package/compiled/src/ifc/geometry_dispatch.d.ts.map +1 -1
- package/compiled/src/ifc/geometry_dispatch.js +261 -5
- package/compiled/src/ifc/geometry_dispatch.test.js +147 -1
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts +54 -0
- package/compiled/src/ifc/ifc_geometry_extraction.d.ts.map +1 -1
- package/compiled/src/ifc/ifc_geometry_extraction.js +153 -20
- package/compiled/src/index.d.ts +1 -1
- package/compiled/src/index.d.ts.map +1 -1
- package/compiled/src/index.js +1 -1
- package/compiled/src/step/dangling_reference_error.d.ts +34 -0
- package/compiled/src/step/dangling_reference_error.d.ts.map +1 -0
- package/compiled/src/step/dangling_reference_error.js +36 -0
- package/compiled/src/step/step_entity_base.d.ts +17 -0
- package/compiled/src/step/step_entity_base.d.ts.map +1 -1
- package/compiled/src/step/step_entity_base.js +28 -4
- package/compiled/src/version/version.js +1 -1
- package/compiled/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
// same geometry ids, same placed transforms — since the durable pump the
|
|
7
7
|
// preview hands over to is already pinned to classic parity.
|
|
8
8
|
import * as fs from "fs";
|
|
9
|
-
import { beforeAll, describe, expect, test } from "@jest/globals";
|
|
9
|
+
import { beforeAll, describe, expect, jest, test } from "@jest/globals";
|
|
10
10
|
import { ConwayGeometry } from "../../../dependencies/conway-geom/index.js";
|
|
11
11
|
import IfcStepParser from "../../ifc/ifc_step_parser.js";
|
|
12
|
+
import Logger from "../../logging/logger.js";
|
|
12
13
|
import { BufferByteSource } from "../../step/parsing/byte_source.js";
|
|
13
14
|
import { ColumnarIndexSink, } from "../../step/parsing/columnar_index.js";
|
|
14
15
|
import { ParseResult } from "../../step/parsing/step_parser.js";
|
|
@@ -380,4 +381,266 @@ describe("StreamedPreviewChannel", () => {
|
|
|
380
381
|
}
|
|
381
382
|
}
|
|
382
383
|
}, 240000);
|
|
384
|
+
test("a tail-placement file recovers its deferred products", () => {
|
|
385
|
+
// The resident twin of the store channel's test for conway#542.
|
|
386
|
+
// data/index_tail_placements.ifc is index_georeferenced_multicell.ifc
|
|
387
|
+
// with every leaf point/direction record moved to the end of DATA —
|
|
388
|
+
// same ids, same text, hostile order. It is the Archicad shape at
|
|
389
|
+
// fixture scale: its products reference a placement chain that bottoms
|
|
390
|
+
// out after them, so an index stopping short of the tail cannot place
|
|
391
|
+
// any of them. The multicell fixture rather than index.ifc because it
|
|
392
|
+
// carries enough products that one attempt cannot exhaust the
|
|
393
|
+
// generation — which is what leaves the preemption path, not the
|
|
394
|
+
// exhaustion path, as the only way to rebuild.
|
|
395
|
+
const tailText = fs.readFileSync("data/index_tail_placements.ifc", "utf8");
|
|
396
|
+
const lines = tailText.split("\n");
|
|
397
|
+
const firstLeaf = lines.findIndex((line) => /=\s*IFC(CARTESIANPOINT|DIRECTION)/.test(line));
|
|
398
|
+
expect(firstLeaf).toBeGreaterThan(0);
|
|
399
|
+
// A genuine prefix, closed off so it parses: every record up to the
|
|
400
|
+
// leaf block, and nothing after it. The full file is stage two.
|
|
401
|
+
const prefixText = `${lines.slice(0, firstLeaf).join("\n")}\nENDSEC;\nEND-ISO-10303-21;\n`;
|
|
402
|
+
const prefixBytes = new Uint8Array(Buffer.from(prefixText, "latin1"));
|
|
403
|
+
const tailBytes = new Uint8Array(Buffer.from(tailText, "latin1"));
|
|
404
|
+
const sink = new ColumnarIndexSink();
|
|
405
|
+
const payloads = [];
|
|
406
|
+
// The source buffer is the WHOLE file throughout, as it is on a
|
|
407
|
+
// resident open — only the index grows.
|
|
408
|
+
const channel = new StreamedPreviewChannel(tailBytes, conwayGeometry, sink, ifcPreviewAdapter(), true, (mesh) => payloads.push(mesh), void 0, void 0, 1);
|
|
409
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
410
|
+
const internals = channel;
|
|
411
|
+
// One unit per tick, so stage one leaves units UNATTEMPTED. That is
|
|
412
|
+
// what forces the preemption path: with units still pending, a channel
|
|
413
|
+
// that only rebuilds on exhaustion keeps its starved generation and
|
|
414
|
+
// never looks at the deferrals again.
|
|
415
|
+
internals.tickBudgetMs_ = Number.MAX_SAFE_INTEGER;
|
|
416
|
+
internals.tickMaxAttempts_ = 1;
|
|
417
|
+
// Stage one: index only the prefix, then let the channel work it.
|
|
418
|
+
expect(buildIndexStreaming(new BufferByteSource(prefixBytes), IfcStepParser.Instance, POOL, void 0, sink).result).toBe(ParseResult.COMPLETE);
|
|
419
|
+
internals.lastInlineTick_ = 0;
|
|
420
|
+
channel.maybeTickInline();
|
|
421
|
+
const afterPrefix = channel.previewYield;
|
|
422
|
+
// The fixture has to actually exercise the path, or the rest proves
|
|
423
|
+
// nothing about it — and units must be left over, or the rebuild would
|
|
424
|
+
// happen by exhaustion and prove nothing about preemption.
|
|
425
|
+
expect(afterPrefix.deferredOnPlacement).toBeGreaterThan(0);
|
|
426
|
+
expect(afterPrefix.emitted).toBe(0);
|
|
427
|
+
expect(afterPrefix.firstMeshMs).toBeUndefined();
|
|
428
|
+
expect(internals.unitOrdinal_)
|
|
429
|
+
.toBeLessThan(internals.generation_.generation.unitCount);
|
|
430
|
+
// Stage two: the same reset-and-replay the streaming builder performs
|
|
431
|
+
// when it grows its window, so top-level localIDs stay in dense parse
|
|
432
|
+
// order and the deferred ORDINALS the channel is holding still mean
|
|
433
|
+
// what they meant (see ColumnarIndexSink.reset).
|
|
434
|
+
sink.reset();
|
|
435
|
+
expect(buildIndexStreaming(new BufferByteSource(tailBytes), IfcStepParser.Instance, POOL, void 0, sink).result).toBe(ParseResult.COMPLETE);
|
|
436
|
+
// Exactly one attempt in this tick. That is what makes this an
|
|
437
|
+
// assertion about PREEMPTION: with units still pending, a channel that
|
|
438
|
+
// rebuilds only on exhaustion spends the attempt on the next fresh unit
|
|
439
|
+
// against the old starved generation, and the retry never happens.
|
|
440
|
+
internals.lastInlineTick_ = 0;
|
|
441
|
+
channel.maybeTickInline();
|
|
442
|
+
const afterFull = channel.previewYield;
|
|
443
|
+
// Both halves of the fix, and `retried` is what separates them from a
|
|
444
|
+
// channel that merely got lucky on a later unit. Without the retry
|
|
445
|
+
// queue a deferred unit is attempted once, at the most index-starved
|
|
446
|
+
// generation it appears in, and abandoned. Without preemptive rebuilds
|
|
447
|
+
// the generation is kept while units remain, so the deferrals are never
|
|
448
|
+
// revisited against the longer index. Either one missing holds this at
|
|
449
|
+
// zero.
|
|
450
|
+
expect(afterFull.retried).toBeGreaterThan(0);
|
|
451
|
+
expect(afterFull.emitted).toBeGreaterThan(0);
|
|
452
|
+
// And the recovered products become pixels: one attempt per tick is
|
|
453
|
+
// what makes the assertions above about preemption, but a single unit
|
|
454
|
+
// need not be one that carries geometry (a site or a storey extracts
|
|
455
|
+
// and walks no buffer geometry), so let the channel run out the
|
|
456
|
+
// recovered queue before reading time-to-first-pixel.
|
|
457
|
+
internals.tickMaxAttempts_ = Number.MAX_SAFE_INTEGER;
|
|
458
|
+
internals.lastInlineTick_ = 0;
|
|
459
|
+
channel.maybeTickInline();
|
|
460
|
+
expect(payloads.length).toBeGreaterThan(0);
|
|
461
|
+
expect(channel.previewYield.firstMeshMs).toBeGreaterThanOrEqual(0);
|
|
462
|
+
channel.stop();
|
|
463
|
+
}, 240000);
|
|
464
|
+
test("a generation is preempted only when it is deferring", () => {
|
|
465
|
+
// The counterweight. Rebuilding on index growth alone regressed the
|
|
466
|
+
// case that already worked: PSB, which defers nothing, went from a
|
|
467
|
+
// first mesh at 269ms to 495ms on the store path because it kept paying
|
|
468
|
+
// for rebuilds it had no use for. index.ifc is that shape at fixture
|
|
469
|
+
// scale, so the same two-stage growth must leave its generation alone.
|
|
470
|
+
const sink = new ColumnarIndexSink();
|
|
471
|
+
const channel = new StreamedPreviewChannel(data, conwayGeometry, sink, ifcPreviewAdapter(), true, () => { }, void 0, void 0, 1);
|
|
472
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
473
|
+
const internals = channel;
|
|
474
|
+
// One unit per tick, so the generation is nowhere near exhausted when
|
|
475
|
+
// the index grows — otherwise the exhaustion path would rebuild and
|
|
476
|
+
// this would assert nothing about preemption.
|
|
477
|
+
internals.tickBudgetMs_ = Number.MAX_SAFE_INTEGER;
|
|
478
|
+
internals.tickMaxAttempts_ = 1;
|
|
479
|
+
expect(buildIndexStreaming(new BufferByteSource(data), IfcStepParser.Instance, POOL, void 0, sink).result).toBe(ParseResult.COMPLETE);
|
|
480
|
+
internals.lastInlineTick_ = 0;
|
|
481
|
+
channel.maybeTickInline();
|
|
482
|
+
const snapshotRecords = internals.lastSnapshotRecords_;
|
|
483
|
+
expect(snapshotRecords).toBeGreaterThan(0);
|
|
484
|
+
expect(channel.previewYield.deferredOnPlacement).toBe(0);
|
|
485
|
+
// Index growth well past GENERATION_GROWTH_FACTOR, with units still
|
|
486
|
+
// pending and nothing deferring: the generation must be kept.
|
|
487
|
+
sink.reset();
|
|
488
|
+
for (let repeat = 0; repeat < 3; ++repeat) {
|
|
489
|
+
expect(buildIndexStreaming(new BufferByteSource(data), IfcStepParser.Instance, POOL, void 0, sink).result).toBe(ParseResult.COMPLETE);
|
|
490
|
+
}
|
|
491
|
+
expect(sink.topLevelCount).toBeGreaterThan(snapshotRecords * 2);
|
|
492
|
+
internals.lastInlineTick_ = 0;
|
|
493
|
+
channel.maybeTickInline();
|
|
494
|
+
expect(internals.lastSnapshotRecords_).toBe(snapshotRecords);
|
|
495
|
+
expect(channel.previewYield.retried).toBe(0);
|
|
496
|
+
channel.stop();
|
|
497
|
+
}, 240000);
|
|
498
|
+
test("retry mode preempts a generation whose units captured nothing", () => {
|
|
499
|
+
// AP214's half of conway#542. `retryEmptyUnits` already re-runs empty
|
|
500
|
+
// units, so that schema never abandoned a deferral — but it kept a
|
|
501
|
+
// stale generation for the same reason the IFC path did: the growth
|
|
502
|
+
// gate sat behind "this generation still has units", and a scan that
|
|
503
|
+
// never finishes never reaches it. An empty unit is this schema's
|
|
504
|
+
// deferral signal (the adapter cannot classify a failure — an assembly
|
|
505
|
+
// unit simply produces no instances until the solids it references are
|
|
506
|
+
// indexed), so index growth must preempt mid-scan.
|
|
507
|
+
const UNIT_COUNT = 3;
|
|
508
|
+
const runsPerGeneration = [];
|
|
509
|
+
let reportedRecords = 2048;
|
|
510
|
+
const fakeSink = {
|
|
511
|
+
get topLevelCount() {
|
|
512
|
+
return reportedRecords;
|
|
513
|
+
},
|
|
514
|
+
snapshot: () => ({}),
|
|
515
|
+
};
|
|
516
|
+
const makeGeneration = () => {
|
|
517
|
+
const runs = [];
|
|
518
|
+
runsPerGeneration.push(runs);
|
|
519
|
+
return {
|
|
520
|
+
// Empty scene: units "execute" but never capture, so no unit ever
|
|
521
|
+
// completes and every generation re-runs all of them.
|
|
522
|
+
scene: { *walk() { } },
|
|
523
|
+
unitCount: UNIT_COUNT,
|
|
524
|
+
linearScalingFactor: 1,
|
|
525
|
+
runUnits: (from) => {
|
|
526
|
+
runs.push(from);
|
|
527
|
+
return 1;
|
|
528
|
+
},
|
|
529
|
+
geometryExpressID: () => void 0,
|
|
530
|
+
recenter: false,
|
|
531
|
+
dispose: () => { },
|
|
532
|
+
};
|
|
533
|
+
};
|
|
534
|
+
const adapter = {
|
|
535
|
+
retryEmptyUnits: true,
|
|
536
|
+
buildGeneration: () => makeGeneration(),
|
|
537
|
+
};
|
|
538
|
+
const channel = new StreamedPreviewChannel(data, conwayGeometry, fakeSink, adapter, false, () => { }, void 0, void 0, 1);
|
|
539
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
540
|
+
const internals = channel;
|
|
541
|
+
// One unit per tick, so the scan is deliberately left unfinished.
|
|
542
|
+
internals.tickBudgetMs_ = Number.MAX_SAFE_INTEGER;
|
|
543
|
+
internals.tickMaxAttempts_ = 1;
|
|
544
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
545
|
+
const forceTick = () => {
|
|
546
|
+
internals.lastInlineTick_ = 0;
|
|
547
|
+
internals.tickIntervalMs_ = 0;
|
|
548
|
+
channel.maybeTickInline();
|
|
549
|
+
};
|
|
550
|
+
// Generation 1 runs one unit, which captures nothing.
|
|
551
|
+
forceTick();
|
|
552
|
+
expect(runsPerGeneration.length).toBe(1);
|
|
553
|
+
expect(runsPerGeneration[0]).toEqual([0]);
|
|
554
|
+
// The index grows past the gate with the scan still mid-list. Without
|
|
555
|
+
// preemption the channel keeps generation 1 and runs its unit 1; with
|
|
556
|
+
// it, a fresh generation restarts the scan against the longer index.
|
|
557
|
+
reportedRecords *= 4;
|
|
558
|
+
forceTick();
|
|
559
|
+
expect(runsPerGeneration.length).toBe(2);
|
|
560
|
+
expect(runsPerGeneration[1]).toEqual([0]);
|
|
561
|
+
channel.stop();
|
|
562
|
+
}, 240000);
|
|
563
|
+
test("preemption preserves the unconsumed suffix of the retry queue", () => {
|
|
564
|
+
// Codex round 1 on #543: preemption replaced retryQueue_ outright with
|
|
565
|
+
// this generation's fresh deferredForRetry_, discarding whatever the
|
|
566
|
+
// OLD queue's tail had not yet been popped. A retry queue can easily
|
|
567
|
+
// span more than one tick's attempt budget (bounded per tick, unbounded
|
|
568
|
+
// in total), so index growth can preempt a generation mid-drain of it
|
|
569
|
+
// — and every un-popped entry is a unit whose unitOrdinal_ has already
|
|
570
|
+
// passed, so replacing rather than concatenating strands it exactly
|
|
571
|
+
// the way abandoned deferrals were stranded before this queue existed
|
|
572
|
+
// (conway#542).
|
|
573
|
+
//
|
|
574
|
+
// The bug is purely mechanical (which array wins the assignment), so
|
|
575
|
+
// this seeds the private queue state directly and forces the growth
|
|
576
|
+
// gate via lastSnapshotRecords_ rather than engineering a real
|
|
577
|
+
// multi-tick deferral sequence.
|
|
578
|
+
const fakeGeneration = () => ({
|
|
579
|
+
scene: { *walk() { } },
|
|
580
|
+
unitCount: 1,
|
|
581
|
+
linearScalingFactor: 1,
|
|
582
|
+
runUnits: () => 0,
|
|
583
|
+
geometryExpressID: () => void 0,
|
|
584
|
+
recenter: false,
|
|
585
|
+
dispose: () => { },
|
|
586
|
+
});
|
|
587
|
+
const fakeSink = {
|
|
588
|
+
get topLevelCount() {
|
|
589
|
+
return 2048;
|
|
590
|
+
},
|
|
591
|
+
snapshot: () => ({}),
|
|
592
|
+
};
|
|
593
|
+
const adapter = { buildGeneration: () => fakeGeneration() };
|
|
594
|
+
const channel = new StreamedPreviewChannel(data, conwayGeometry, fakeSink, adapter, false, () => { }, void 0, void 0, 1);
|
|
595
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
596
|
+
const internals = channel;
|
|
597
|
+
// Generation 1: a real, successful build (active must be defined for
|
|
598
|
+
// the preemption branch to even be reachable).
|
|
599
|
+
expect(internals.ensureGeneration_()).toBe(true);
|
|
600
|
+
// A retry queue spanning more than one tick's budget: 6 queued
|
|
601
|
+
// retries, only the first 3 consumed (retryCursor_ short of
|
|
602
|
+
// retryQueue_.length is exactly "mid-drain") before the index grew
|
|
603
|
+
// again. deferredForRetry_ is this generation's OWN fresh deferral —
|
|
604
|
+
// the only thing the buggy version kept.
|
|
605
|
+
internals.retryQueue_ = [10, 11, 12, 13, 14, 15];
|
|
606
|
+
internals.retryCursor_ = 3;
|
|
607
|
+
internals.deferredForRetry_ = [99];
|
|
608
|
+
// Force the growth gate trivially open on the next check, without
|
|
609
|
+
// needing the sink to actually grow: the gate is a ratio against
|
|
610
|
+
// lastSnapshotRecords_, not an absolute count.
|
|
611
|
+
internals.lastSnapshotRecords_ = 1;
|
|
612
|
+
// Preemption fires: active is defined, growthReady (2048 >= 1 * factor),
|
|
613
|
+
// and hasDeferred_() is true (deferredForRetry_.length > 0).
|
|
614
|
+
expect(internals.ensureGeneration_()).toBe(true);
|
|
615
|
+
// The unconsumed suffix of the old queue (indices 3..5) must survive,
|
|
616
|
+
// carried ahead of this generation's own fresh deferral — not replaced
|
|
617
|
+
// by it.
|
|
618
|
+
expect(internals.retryQueue_).toEqual([13, 14, 15, 99]);
|
|
619
|
+
expect(internals.retryCursor_).toBe(0);
|
|
620
|
+
channel.stop();
|
|
621
|
+
}, 240000);
|
|
622
|
+
test("reports a preview line even when nothing was ever attempted", () => {
|
|
623
|
+
// Codex round 1 on #543: stop() suppressed the Preview line unless
|
|
624
|
+
// emittedUnits_ or deferredUnits_ was nonzero. A channel that never
|
|
625
|
+
// reached firstGenerationMinRecords -- or whose every generation build
|
|
626
|
+
// threw -- leaves both at zero, and that is exactly the worst-case
|
|
627
|
+
// blank-first-load conway#542 exists to make diagnosable: an enabled
|
|
628
|
+
// preview that produced nothing must not read the same as a preview
|
|
629
|
+
// that never ran. formatPreviewLine already renders the zero case as
|
|
630
|
+
// "no mesh, 0 meshes from 0 units, 0 deferred".
|
|
631
|
+
const fakeSink = {
|
|
632
|
+
get topLevelCount() {
|
|
633
|
+
return 0;
|
|
634
|
+
},
|
|
635
|
+
snapshot: () => ({}),
|
|
636
|
+
};
|
|
637
|
+
const infoSpy = jest.spyOn(Logger, "info").mockImplementation(() => { });
|
|
638
|
+
// Default firstGenerationMinRecords (1024): with topLevelCount pinned
|
|
639
|
+
// at 0, ensureGeneration_ never builds a generation, so the channel
|
|
640
|
+
// reaches stop() having attempted nothing at all.
|
|
641
|
+
const channel = new StreamedPreviewChannel(data, conwayGeometry, fakeSink, { buildGeneration: () => { throw new Error("must not be called"); } }, false, () => { });
|
|
642
|
+
channel.stop();
|
|
643
|
+
expect(infoSpy).toHaveBeenCalledWith(expect.stringContaining("Preview: no mesh, 0 meshes from 0 units, 0 deferred"));
|
|
644
|
+
infoSpy.mockRestore();
|
|
645
|
+
});
|
|
383
646
|
});
|
|
@@ -155,6 +155,18 @@ export declare class IfcApiProxyIfc implements IfcApiModelPassthrough {
|
|
|
155
155
|
* large-coordinate budget.
|
|
156
156
|
*/
|
|
157
157
|
private demandCoordinationFromPreview_;
|
|
158
|
+
/**
|
|
159
|
+
* True when the coordination frame was HANDED to this instance rather than
|
|
160
|
+
* derived from its own first geometry (see setCoordinationFrame).
|
|
161
|
+
*
|
|
162
|
+
* The distinction is what makes a recentred model shardable. A derived
|
|
163
|
+
* frame is anchored on whichever product this instance happened to extract
|
|
164
|
+
* first, so N workers derive N frames and their outputs merge shifted by
|
|
165
|
+
* whole recentre cells; a supplied one is the same for every worker by
|
|
166
|
+
* construction, which is the only property the refusals in
|
|
167
|
+
* checkShardPreconditions_ were ever protecting.
|
|
168
|
+
*/
|
|
169
|
+
private coordinationSupplied_;
|
|
158
170
|
_isCoordinated: boolean;
|
|
159
171
|
linearScalingFactor: number;
|
|
160
172
|
identity: number[];
|
|
@@ -577,6 +589,98 @@ export declare class IfcApiProxyIfc implements IfcApiModelPassthrough {
|
|
|
577
589
|
* rel-aggregates). Shared by the sync and async pumps.
|
|
578
590
|
*/
|
|
579
591
|
private ensureDemandWorklists_;
|
|
592
|
+
/**
|
|
593
|
+
* Worklist build for a windowed source — the same partition, with the
|
|
594
|
+
* dispatch walk's records paged before they are read.
|
|
595
|
+
*
|
|
596
|
+
* Sharding a windowed model rests on every worker computing the SAME key
|
|
597
|
+
* for a product, and an inline walk cannot promise that: whether a record
|
|
598
|
+
* read resolves depends on which chunks THIS worker holds, so workers
|
|
599
|
+
* disagree and both moduli select a product (extracted twice) or neither
|
|
600
|
+
* (dropped). computeDispatchKeys pages each hop of the walk first, which
|
|
601
|
+
* is what makes the keys a function of the file rather than of paging —
|
|
602
|
+
* and is why the pool can finally serve a store-backed open, the only kind
|
|
603
|
+
* Share performs.
|
|
604
|
+
*
|
|
605
|
+
* Resident sources take the same route with the paging short-circuited, so
|
|
606
|
+
* there is one partition rather than a windowed one and a resident one.
|
|
607
|
+
*/
|
|
608
|
+
private ensureDemandWorklistsAsync_;
|
|
609
|
+
/**
|
|
610
|
+
* Everything the pump could extract, before any shard narrows it.
|
|
611
|
+
*
|
|
612
|
+
* Unchanged from what the pump enumerated before sharding existed, and
|
|
613
|
+
* deliberately shared by both key computations so they start from the same
|
|
614
|
+
* lists in the same order — that order is what makes the keys align to the
|
|
615
|
+
* worklists.
|
|
616
|
+
*
|
|
617
|
+
* The product walk itself reads no record bytes (the type index and the
|
|
618
|
+
* local-ID column answer it). `aggregateTargetLocalIDs` does scan the
|
|
619
|
+
* IfcRelAggregates records, so a windowed caller must have paged them —
|
|
620
|
+
* `ensureDemandWorklistsAsync_` does, and carries the reasoning.
|
|
621
|
+
*
|
|
622
|
+
* @return {object} The unsharded product and rel-aggregates worklists.
|
|
623
|
+
*/
|
|
624
|
+
private collectDemandCandidates_;
|
|
625
|
+
/**
|
|
626
|
+
* Install the whole model's worklists — the unsharded case.
|
|
627
|
+
*
|
|
628
|
+
* @param products Every extractable product, in index order.
|
|
629
|
+
* @param aggregates Every rel-aggregates entry, in index order.
|
|
630
|
+
*/
|
|
631
|
+
private adoptDemandWorklists_;
|
|
632
|
+
/**
|
|
633
|
+
* Install the worklists narrowed to this instance's shard.
|
|
634
|
+
*
|
|
635
|
+
* Keys are passed in rather than computed here because where they come
|
|
636
|
+
* from is the whole difference between a resident and a windowed source —
|
|
637
|
+
* one walks the attributes directly, the other pages the walk's closure
|
|
638
|
+
* first — while the narrowing itself is identical. Separate from
|
|
639
|
+
* {@link adoptDemandWorklists_} so the keys are required by the signature
|
|
640
|
+
* rather than by a comment.
|
|
641
|
+
*
|
|
642
|
+
* @param products Every extractable product, in index order.
|
|
643
|
+
* @param aggregates Every rel-aggregates entry, in index order.
|
|
644
|
+
* @param productKeys Placement keys aligned to `products`.
|
|
645
|
+
* @param aggregateKeys Placement keys aligned to `aggregates`.
|
|
646
|
+
*/
|
|
647
|
+
private adoptShardedWorklists_;
|
|
648
|
+
/**
|
|
649
|
+
* Hand this model the recentre frame to apply, instead of letting it
|
|
650
|
+
* derive one — the other half of what a worker pool needs.
|
|
651
|
+
*
|
|
652
|
+
* `COORDINATE_TO_ORIGIN` normally recentres a model onto an anchor taken
|
|
653
|
+
* from the FIRST geometry the instance captures. That is fine for one
|
|
654
|
+
* instance and fatal for N: each worker starts on a different product, so
|
|
655
|
+
* each derives a different frame, and a model spanning more than one
|
|
656
|
+
* recentre cell reassembles with its shards offset by whole cells. Nothing
|
|
657
|
+
* downstream can detect it — the placements are individually plausible.
|
|
658
|
+
*
|
|
659
|
+
* So the frame becomes an input. A coordinator derives it once (Share's
|
|
660
|
+
* parse-time preview channel already does, and
|
|
661
|
+
* {@link getAppliedCoordination} reports what any instance applied), hands
|
|
662
|
+
* the same matrix to every worker, and the shards agree by construction
|
|
663
|
+
* rather than by luck. This is what lifts the COORDINATE_TO_ORIGIN refusal
|
|
664
|
+
* in {@link setGeometryShard}.
|
|
665
|
+
*
|
|
666
|
+
* A supplied frame is FINAL. The adopted-preview path re-derives when the
|
|
667
|
+
* first durable placement lands outside the large-coordinate budget
|
|
668
|
+
* (Share#1634); that check is disabled here, because a worker that
|
|
669
|
+
* re-derived would silently leave the frame its siblings are still using.
|
|
670
|
+
* A coordinator that wants that validation runs it on its own instance,
|
|
671
|
+
* before it hands the frame out.
|
|
672
|
+
*
|
|
673
|
+
* Deferred models only, like sharding itself: a classic open has already
|
|
674
|
+
* placed everything by the time this could be called.
|
|
675
|
+
*
|
|
676
|
+
* Supply it BEFORE claiming a shard: {@link setGeometryShard} refuses a
|
|
677
|
+
* COORDINATE_TO_ORIGIN model that has no frame yet, so the reverse order
|
|
678
|
+
* fails at the claim rather than at the pump.
|
|
679
|
+
*
|
|
680
|
+
* @param matrix Column-major mat4 of 16 finite numbers, or undefined to
|
|
681
|
+
* drop a previously supplied frame and go back to deriving.
|
|
682
|
+
*/
|
|
683
|
+
setCoordinationFrame(matrix?: number[]): void;
|
|
580
684
|
/**
|
|
581
685
|
* Extract only one shard of this model's geometry — the across-product
|
|
582
686
|
* parallelism seam.
|
|
@@ -635,12 +739,19 @@ export declare class IfcApiProxyIfc implements IfcApiModelPassthrough {
|
|
|
635
739
|
* it is the third such window found in this review; patching each one as
|
|
636
740
|
* it turns up is losing strategy.
|
|
637
741
|
*
|
|
638
|
-
* So a sharded model never
|
|
639
|
-
* instant
|
|
640
|
-
*
|
|
641
|
-
*
|
|
742
|
+
* So a sharded model never DERIVES a frame, whatever the flag says at the
|
|
743
|
+
* instant one would be derived. The refusals still fire first in every
|
|
744
|
+
* observable case, which is what a caller should see; this is what makes a
|
|
745
|
+
* missed one merely refused-late rather than silently wrong.
|
|
746
|
+
*
|
|
747
|
+
* Deriving is all this governs. A frame handed in by
|
|
748
|
+
* {@link setCoordinationFrame} is applied by the capture path
|
|
749
|
+
* unconditionally — that is the point of supplying one — and this staying
|
|
750
|
+
* false for a sharded model is exactly what keeps a worker from deriving
|
|
751
|
+
* over the top of it.
|
|
642
752
|
*
|
|
643
|
-
* @return {boolean} Whether to derive
|
|
753
|
+
* @return {boolean} Whether to derive a recentre frame from this
|
|
754
|
+
* instance's first geometry.
|
|
644
755
|
*/
|
|
645
756
|
private recentreEnabled_;
|
|
646
757
|
private checkShardPreconditions_;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ifc_api_proxy_ifc.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/ifc_api_proxy_ifc.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACf,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"ifc_api_proxy_ifc.d.ts","sourceRoot":"","sources":["../../../../src/compat/web-ifc/ifc_api_proxy_ifc.ts"],"names":[],"mappings":"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"}
|