@loaders.gl/core 5.0.0-alpha.5 → 5.0.0-alpha.7
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/dist/dist.dev.js +398 -49
- package/dist/dist.min.js +3 -3
- package/dist/index.cjs +405 -51
- package/dist/index.cjs.map +3 -3
- package/dist/lib/api/parse-in-batches.d.ts.map +1 -1
- package/dist/lib/api/parse-in-batches.js +6 -2
- package/dist/lib/api/parse-in-batches.js.map +1 -1
- package/dist/lib/api/parse.js +2 -2
- package/dist/lib/api/parse.js.map +1 -1
- package/dist/lib/init.js +1 -1
- package/dist/lib/loader-utils/get-fetch-function.d.ts.map +1 -1
- package/dist/lib/loader-utils/get-fetch-function.js +2 -1
- package/dist/lib/loader-utils/get-fetch-function.js.map +1 -1
- package/dist/lib/loader-utils/loader-context.d.ts +1 -1
- package/dist/lib/loader-utils/loader-context.d.ts.map +1 -1
- package/dist/lib/loader-utils/loader-context.js +6 -3
- package/dist/lib/loader-utils/loader-context.js.map +1 -1
- package/dist/lib/loader-utils/option-defaults.d.ts.map +1 -1
- package/dist/lib/loader-utils/option-defaults.js +1 -0
- package/dist/lib/loader-utils/option-defaults.js.map +1 -1
- package/dist/lib/loader-utils/option-utils.d.ts.map +1 -1
- package/dist/lib/loader-utils/option-utils.js +12 -1
- package/dist/lib/loader-utils/option-utils.js.map +1 -1
- package/dist/null-loader.js +1 -1
- package/dist/null-worker-node.js +29 -3
- package/dist/null-worker.js +29 -3
- package/package.json +6 -6
- package/src/lib/api/parse-in-batches.ts +11 -2
- package/src/lib/api/parse.ts +2 -2
- package/src/lib/loader-utils/get-fetch-function.ts +2 -1
- package/src/lib/loader-utils/loader-context.ts +6 -3
- package/src/lib/loader-utils/option-defaults.ts +1 -0
- package/src/lib/loader-utils/option-utils.ts +13 -1
package/dist/index.cjs
CHANGED
|
@@ -401,6 +401,10 @@ var WorkerThread = class {
|
|
|
401
401
|
name;
|
|
402
402
|
source;
|
|
403
403
|
url;
|
|
404
|
+
/** Lazily resolves the classic worker URL used as a fallback. */
|
|
405
|
+
getUrl;
|
|
406
|
+
/** Creates a browser Worker directly. */
|
|
407
|
+
loadWorker;
|
|
404
408
|
terminated = false;
|
|
405
409
|
worker;
|
|
406
410
|
onMessage;
|
|
@@ -411,11 +415,13 @@ var WorkerThread = class {
|
|
|
411
415
|
return typeof Worker !== "undefined" && isBrowser2 || typeof NodeWorker !== "undefined" && !isBrowser2;
|
|
412
416
|
}
|
|
413
417
|
constructor(props) {
|
|
414
|
-
const { name, source, url } = props;
|
|
415
|
-
assert2(source || url);
|
|
418
|
+
const { name, source, url, getUrl, loadWorker } = props;
|
|
419
|
+
assert2(source || url || getUrl || loadWorker);
|
|
416
420
|
this.name = name;
|
|
417
421
|
this.source = source;
|
|
418
422
|
this.url = url;
|
|
423
|
+
this.getUrl = getUrl;
|
|
424
|
+
this.loadWorker = loadWorker;
|
|
419
425
|
this.onMessage = NOOP;
|
|
420
426
|
this.onError = (error) => console.log(error);
|
|
421
427
|
this.worker = isBrowser2 ? this._createBrowserWorker() : this._createNodeWorker();
|
|
@@ -461,7 +467,7 @@ var WorkerThread = class {
|
|
|
461
467
|
*/
|
|
462
468
|
_getErrorFromErrorEvent(event) {
|
|
463
469
|
let message = "Failed to load ";
|
|
464
|
-
message += `worker ${this.name} from ${this.url}. `;
|
|
470
|
+
message += `worker ${this.name} from ${this.url || "built-in worker factory"}. `;
|
|
465
471
|
if (event.message) {
|
|
466
472
|
message += `${event.message} in `;
|
|
467
473
|
}
|
|
@@ -474,8 +480,26 @@ var WorkerThread = class {
|
|
|
474
480
|
* Creates a worker thread on the browser
|
|
475
481
|
*/
|
|
476
482
|
_createBrowserWorker() {
|
|
477
|
-
|
|
483
|
+
var _a;
|
|
484
|
+
if (this.loadWorker) {
|
|
485
|
+
try {
|
|
486
|
+
const worker2 = this.loadWorker();
|
|
487
|
+
if (worker2) {
|
|
488
|
+
return this._initializeBrowserWorker(worker2);
|
|
489
|
+
}
|
|
490
|
+
} catch (error) {
|
|
491
|
+
if (!this.source && !this.url && !this.getUrl) {
|
|
492
|
+
throw error;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const url = this.url || ((_a = this.getUrl) == null ? void 0 : _a.call(this));
|
|
497
|
+
this._loadableURL = getLoadableWorkerURL({ source: this.source, url });
|
|
478
498
|
const worker = new Worker(this._loadableURL, { name: this.name });
|
|
499
|
+
return this._initializeBrowserWorker(worker);
|
|
500
|
+
}
|
|
501
|
+
/** Attaches protocol handlers to a browser worker. */
|
|
502
|
+
_initializeBrowserWorker(worker) {
|
|
479
503
|
worker.onmessage = (event) => {
|
|
480
504
|
if (!event.data) {
|
|
481
505
|
this.onError(new Error("No data received"));
|
|
@@ -525,6 +549,10 @@ var WorkerPool = class {
|
|
|
525
549
|
source;
|
|
526
550
|
// | Function;
|
|
527
551
|
url;
|
|
552
|
+
/** Lazily resolves a classic worker fallback URL. */
|
|
553
|
+
getUrl;
|
|
554
|
+
/** Creates a browser Worker directly. */
|
|
555
|
+
loadWorker;
|
|
528
556
|
maxConcurrency = 1;
|
|
529
557
|
maxMobileConcurrency = 1;
|
|
530
558
|
onDebug = () => {
|
|
@@ -533,6 +561,7 @@ var WorkerPool = class {
|
|
|
533
561
|
props = {};
|
|
534
562
|
jobQueue = [];
|
|
535
563
|
idleQueue = [];
|
|
564
|
+
activeJobs = /* @__PURE__ */ new Set();
|
|
536
565
|
count = 0;
|
|
537
566
|
isDestroyed = false;
|
|
538
567
|
/** Checks if workers are supported on this platform */
|
|
@@ -546,13 +575,19 @@ var WorkerPool = class {
|
|
|
546
575
|
constructor(props) {
|
|
547
576
|
this.source = props.source;
|
|
548
577
|
this.url = props.url;
|
|
578
|
+
this.getUrl = props.getUrl;
|
|
579
|
+
this.loadWorker = props.loadWorker;
|
|
549
580
|
this.setProps(props);
|
|
550
581
|
}
|
|
551
582
|
/**
|
|
552
|
-
* Terminates all workers in the pool
|
|
583
|
+
* Terminates all workers in the pool and aborts active jobs.
|
|
584
|
+
* @param reason Optional error delivered to active jobs.
|
|
553
585
|
* @note Can free up significant memory
|
|
554
586
|
*/
|
|
555
|
-
destroy() {
|
|
587
|
+
destroy(reason = new Error("Worker pool was destroyed")) {
|
|
588
|
+
this.activeJobs.forEach((job) => job.abort(reason));
|
|
589
|
+
const queuedJobs = this.jobQueue.splice(0);
|
|
590
|
+
queuedJobs.forEach((queuedJob) => queuedJob.onReject(reason));
|
|
556
591
|
this.idleQueue.forEach((worker) => worker.destroy());
|
|
557
592
|
this.isDestroyed = true;
|
|
558
593
|
}
|
|
@@ -575,8 +610,11 @@ var WorkerPool = class {
|
|
|
575
610
|
}
|
|
576
611
|
}
|
|
577
612
|
async startJob(name, onMessage2 = (job, type, data) => job.done(data), onError = (job, error) => job.error(error)) {
|
|
578
|
-
|
|
579
|
-
|
|
613
|
+
if (this.isDestroyed) {
|
|
614
|
+
return Promise.reject(new Error("Worker pool was destroyed"));
|
|
615
|
+
}
|
|
616
|
+
const startPromise = new Promise((onStart, onReject) => {
|
|
617
|
+
this.jobQueue.push({ name, onMessage: onMessage2, onError, onStart, onReject });
|
|
580
618
|
return this;
|
|
581
619
|
});
|
|
582
620
|
this._startQueuedJob();
|
|
@@ -604,6 +642,7 @@ var WorkerPool = class {
|
|
|
604
642
|
backlog: this.jobQueue.length
|
|
605
643
|
});
|
|
606
644
|
const job = new WorkerJob(queuedJob.name, workerThread);
|
|
645
|
+
this.activeJobs.add(job);
|
|
607
646
|
workerThread.ref();
|
|
608
647
|
workerThread.onMessage = (data) => queuedJob.onMessage(job, data.type, data.payload);
|
|
609
648
|
workerThread.onError = (error) => queuedJob.onError(job, error);
|
|
@@ -612,6 +651,7 @@ var WorkerPool = class {
|
|
|
612
651
|
await job.result;
|
|
613
652
|
} catch {
|
|
614
653
|
} finally {
|
|
654
|
+
this.activeJobs.delete(job);
|
|
615
655
|
this.returnWorkerToQueue(workerThread);
|
|
616
656
|
}
|
|
617
657
|
}
|
|
@@ -655,7 +695,13 @@ var WorkerPool = class {
|
|
|
655
695
|
if (this.count < this._getMaxConcurrency()) {
|
|
656
696
|
this.count++;
|
|
657
697
|
const name = `${this.name.toLowerCase()} (#${this.count} of ${this.maxConcurrency})`;
|
|
658
|
-
return new WorkerThread({
|
|
698
|
+
return new WorkerThread({
|
|
699
|
+
name,
|
|
700
|
+
source: this.source,
|
|
701
|
+
url: this.url,
|
|
702
|
+
getUrl: this.getUrl,
|
|
703
|
+
loadWorker: this.loadWorker
|
|
704
|
+
});
|
|
659
705
|
}
|
|
660
706
|
return null;
|
|
661
707
|
}
|
|
@@ -672,6 +718,8 @@ var DEFAULT_PROPS = {
|
|
|
672
718
|
onDebug: () => {
|
|
673
719
|
}
|
|
674
720
|
};
|
|
721
|
+
var loadWorkerIds = /* @__PURE__ */ new WeakMap();
|
|
722
|
+
var nextLoadWorkerId = 1;
|
|
675
723
|
var WorkerFarm = class _WorkerFarm {
|
|
676
724
|
props;
|
|
677
725
|
workerPools = /* @__PURE__ */ new Map();
|
|
@@ -694,12 +742,13 @@ var WorkerFarm = class _WorkerFarm {
|
|
|
694
742
|
this.workerPools = /* @__PURE__ */ new Map();
|
|
695
743
|
}
|
|
696
744
|
/**
|
|
697
|
-
* Terminate all workers in the farm
|
|
745
|
+
* Terminate all workers in the farm and abort active jobs.
|
|
746
|
+
* @param reason Optional error delivered to active jobs.
|
|
698
747
|
* @note Can free up significant memory
|
|
699
748
|
*/
|
|
700
|
-
destroy() {
|
|
749
|
+
destroy(reason) {
|
|
701
750
|
for (const workerPool of this.workerPools.values()) {
|
|
702
|
-
workerPool.destroy();
|
|
751
|
+
workerPool.destroy(reason);
|
|
703
752
|
}
|
|
704
753
|
this.workerPools = /* @__PURE__ */ new Map();
|
|
705
754
|
}
|
|
@@ -715,24 +764,28 @@ var WorkerFarm = class _WorkerFarm {
|
|
|
715
764
|
}
|
|
716
765
|
/**
|
|
717
766
|
* Returns a worker pool for the specified worker
|
|
718
|
-
* @param options
|
|
719
|
-
* @param options.name
|
|
720
|
-
* @param options.url
|
|
721
|
-
* @param options.source
|
|
767
|
+
* @param options Worker target used to identify and initialize the pool.
|
|
768
|
+
* @param options.name Worker name used as the base pool identity.
|
|
769
|
+
* @param options.url Worker script URL.
|
|
770
|
+
* @param options.source Inline worker source.
|
|
771
|
+
* @param options.loadWorker Built-in browser worker factory.
|
|
722
772
|
* @example
|
|
723
773
|
* const job = WorkerFarm.getWorkerFarm().getWorkerPool({name, url}).startJob(...);
|
|
724
774
|
*/
|
|
725
775
|
getWorkerPool(options) {
|
|
726
|
-
const { name, source, url } = options;
|
|
727
|
-
|
|
776
|
+
const { name, source, url, getUrl, loadWorker } = options;
|
|
777
|
+
const workerPoolKey = getWorkerPoolKey(options);
|
|
778
|
+
let workerPool = this.workerPools.get(workerPoolKey);
|
|
728
779
|
if (!workerPool) {
|
|
729
780
|
workerPool = new WorkerPool({
|
|
730
781
|
name,
|
|
731
782
|
source,
|
|
732
|
-
url
|
|
783
|
+
url,
|
|
784
|
+
getUrl,
|
|
785
|
+
loadWorker
|
|
733
786
|
});
|
|
734
787
|
workerPool.setProps(this._getWorkerPoolProps());
|
|
735
|
-
this.workerPools.set(
|
|
788
|
+
this.workerPools.set(workerPoolKey, workerPool);
|
|
736
789
|
}
|
|
737
790
|
return workerPool;
|
|
738
791
|
}
|
|
@@ -745,6 +798,91 @@ var WorkerFarm = class _WorkerFarm {
|
|
|
745
798
|
};
|
|
746
799
|
}
|
|
747
800
|
};
|
|
801
|
+
function getWorkerPoolKey(options) {
|
|
802
|
+
const { name, source, url, urlKey, loadWorker } = options;
|
|
803
|
+
const sourceKey = source ? `source:${source}` : "";
|
|
804
|
+
const urlKeyPart = url || urlKey ? `url:${url || urlKey}` : "";
|
|
805
|
+
const loadWorkerKey = loadWorker ? `loadWorker:${getLoadWorkerId(loadWorker)}` : "";
|
|
806
|
+
return [name, sourceKey, urlKeyPart, loadWorkerKey].filter(Boolean).join("|");
|
|
807
|
+
}
|
|
808
|
+
function getLoadWorkerId(loadWorker) {
|
|
809
|
+
let loadWorkerId = loadWorkerIds.get(loadWorker);
|
|
810
|
+
if (!loadWorkerId) {
|
|
811
|
+
loadWorkerId = nextLoadWorkerId++;
|
|
812
|
+
loadWorkerIds.set(loadWorker, loadWorkerId);
|
|
813
|
+
}
|
|
814
|
+
return loadWorkerId;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// ../worker-utils/src/lib/async-queue/async-queue.ts
|
|
818
|
+
var AsyncQueue = class {
|
|
819
|
+
_values;
|
|
820
|
+
_settlers;
|
|
821
|
+
_closed;
|
|
822
|
+
constructor() {
|
|
823
|
+
this._values = [];
|
|
824
|
+
this._settlers = [];
|
|
825
|
+
this._closed = false;
|
|
826
|
+
}
|
|
827
|
+
/** Return an async iterator for this queue */
|
|
828
|
+
[Symbol.asyncIterator]() {
|
|
829
|
+
return this;
|
|
830
|
+
}
|
|
831
|
+
/** Push a new value - the async iterator will yield a promise resolved to this value */
|
|
832
|
+
push(value) {
|
|
833
|
+
return this.enqueue(value);
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Push a new value - the async iterator will yield a promise resolved to this value
|
|
837
|
+
* Add an error - the async iterator will yield a promise rejected with this value
|
|
838
|
+
*/
|
|
839
|
+
enqueue(value) {
|
|
840
|
+
if (this._closed) {
|
|
841
|
+
throw new Error("Closed");
|
|
842
|
+
}
|
|
843
|
+
if (this._settlers.length > 0) {
|
|
844
|
+
if (this._values.length > 0) {
|
|
845
|
+
throw new Error("Illegal internal state");
|
|
846
|
+
}
|
|
847
|
+
const settler = this._settlers.shift();
|
|
848
|
+
if (value instanceof Error) {
|
|
849
|
+
settler.reject(value);
|
|
850
|
+
} else {
|
|
851
|
+
settler.resolve({ value });
|
|
852
|
+
}
|
|
853
|
+
} else {
|
|
854
|
+
this._values.push(value);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
/** Indicate that we not waiting for more values - The async iterator will be done */
|
|
858
|
+
close() {
|
|
859
|
+
while (this._settlers.length > 0) {
|
|
860
|
+
const settler = this._settlers.shift();
|
|
861
|
+
settler.resolve({ done: true });
|
|
862
|
+
}
|
|
863
|
+
this._closed = true;
|
|
864
|
+
}
|
|
865
|
+
// ITERATOR IMPLEMENTATION
|
|
866
|
+
/** @returns a Promise for an IteratorResult */
|
|
867
|
+
next() {
|
|
868
|
+
if (this._values.length > 0) {
|
|
869
|
+
const value = this._values.shift();
|
|
870
|
+
if (value instanceof Error) {
|
|
871
|
+
return Promise.reject(value);
|
|
872
|
+
}
|
|
873
|
+
return Promise.resolve({ done: false, value });
|
|
874
|
+
}
|
|
875
|
+
if (this._closed) {
|
|
876
|
+
if (this._settlers.length > 0) {
|
|
877
|
+
throw new Error("Illegal internal state");
|
|
878
|
+
}
|
|
879
|
+
return Promise.resolve({ done: true, value: void 0 });
|
|
880
|
+
}
|
|
881
|
+
return new Promise((resolve2, reject) => {
|
|
882
|
+
this._settlers.push({ resolve: resolve2, reject });
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
};
|
|
748
886
|
|
|
749
887
|
// ../worker-utils/src/lib/worker-api/get-worker-url.ts
|
|
750
888
|
var warnedWorkerVersionFallbacks = /* @__PURE__ */ new Set();
|
|
@@ -752,35 +890,42 @@ function getWorkerName(worker) {
|
|
|
752
890
|
const warning = worker.version !== VERSION2 ? ` (worker-utils@${VERSION2})` : "";
|
|
753
891
|
return `${worker.name}@${worker.version}${warning}`;
|
|
754
892
|
}
|
|
755
|
-
function
|
|
893
|
+
function getCustomWorkerURL(worker, options = {}) {
|
|
756
894
|
var _a;
|
|
757
895
|
const workerOptions = options[worker.id] || {};
|
|
758
|
-
const workerFile = isBrowser2 ? `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
|
|
896
|
+
const workerFile = isBrowser2 ? worker.workerFile || `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
|
|
759
897
|
let url = workerOptions.workerUrl;
|
|
760
|
-
if (!url && typeof worker.worker === "string") {
|
|
761
|
-
url = worker.worker;
|
|
762
|
-
}
|
|
763
898
|
if (!url && worker.id === "compression") {
|
|
764
899
|
url = options.workerUrl;
|
|
765
900
|
}
|
|
766
901
|
const workerType = options._workerType || ((_a = options == null ? void 0 : options.core) == null ? void 0 : _a._workerType);
|
|
767
|
-
if (workerType === "test") {
|
|
902
|
+
if (!url && workerType === "test") {
|
|
768
903
|
if (isBrowser2) {
|
|
769
904
|
url = `modules/${worker.module}/dist/${workerFile}`;
|
|
770
905
|
} else {
|
|
771
906
|
url = `modules/${worker.module}/src/workers/${worker.id}-worker-node.ts`;
|
|
772
907
|
}
|
|
773
908
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
909
|
+
return url || null;
|
|
910
|
+
}
|
|
911
|
+
function getWorkerURL(worker, options = {}) {
|
|
912
|
+
const customWorkerUrl = getCustomWorkerURL(worker, options);
|
|
913
|
+
const descriptorWorkerUrl = typeof worker.worker === "string" ? worker.worker : null;
|
|
914
|
+
const url = customWorkerUrl || descriptorWorkerUrl || getDefaultWorkerURL(worker, true);
|
|
915
|
+
assert2(url);
|
|
916
|
+
return url;
|
|
917
|
+
}
|
|
918
|
+
function getDefaultWorkerURL(worker, warn = false) {
|
|
919
|
+
const workerFile = isBrowser2 ? worker.workerFile || `${worker.id}-worker.js` : worker.workerNode || `${worker.id}-worker-node.js`;
|
|
920
|
+
let version2 = worker.version;
|
|
921
|
+
if (version2 === "latest") {
|
|
922
|
+
version2 = NPM_TAG;
|
|
923
|
+
}
|
|
924
|
+
const versionTag = version2 ? `@${version2}` : "";
|
|
925
|
+
const url = `https://unpkg.com/@loaders.gl/${worker.module}${versionTag}/dist/${workerFile}`;
|
|
926
|
+
if (warn) {
|
|
781
927
|
warnIfUsingNpmTagFallback(worker, url);
|
|
782
928
|
}
|
|
783
|
-
assert2(url);
|
|
784
929
|
return url;
|
|
785
930
|
}
|
|
786
931
|
function warnIfUsingNpmTagFallback(worker, url) {
|
|
@@ -803,19 +948,16 @@ function canProcessOnWorker(worker, options) {
|
|
|
803
948
|
return false;
|
|
804
949
|
}
|
|
805
950
|
const workerOptions = options == null ? void 0 : options[worker.id];
|
|
806
|
-
return Boolean(
|
|
951
|
+
return Boolean(
|
|
952
|
+
(worker.worker || worker.loadWorker || (workerOptions == null ? void 0 : workerOptions.workerUrl)) && (options == null ? void 0 : options.worker)
|
|
953
|
+
);
|
|
807
954
|
}
|
|
808
955
|
async function processOnWorker(worker, data, options = {}, context = {}, jobContext = {}) {
|
|
809
956
|
var _a, _b, _c;
|
|
810
957
|
throwIfAborted(options.signal);
|
|
811
958
|
const name = getWorkerName(worker);
|
|
812
959
|
const workerFarm = WorkerFarm.getWorkerFarm(options);
|
|
813
|
-
const
|
|
814
|
-
const workerPoolProps = { name, source };
|
|
815
|
-
if (!source) {
|
|
816
|
-
workerPoolProps.url = getWorkerURL(worker, options);
|
|
817
|
-
}
|
|
818
|
-
const workerPool = workerFarm.getWorkerPool(workerPoolProps);
|
|
960
|
+
const workerPool = workerFarm.getWorkerPool(getWorkerPoolTarget(worker, options, name));
|
|
819
961
|
const jobName = options.jobName || worker.name;
|
|
820
962
|
const job = await workerPool.startJob(
|
|
821
963
|
jobName,
|
|
@@ -844,6 +986,115 @@ async function processOnWorker(worker, data, options = {}, context = {}, jobCont
|
|
|
844
986
|
(_c = options.signal) == null ? void 0 : _c.removeEventListener("abort", abortJob);
|
|
845
987
|
}
|
|
846
988
|
}
|
|
989
|
+
function processOnWorkerInBatches(worker, input, options = {}, context = {}, jobContext = {}) {
|
|
990
|
+
return processOnWorkerInBatchesIterator(worker, input, options, context, jobContext);
|
|
991
|
+
}
|
|
992
|
+
async function* processOnWorkerInBatchesIterator(worker, input, options, context, jobContext) {
|
|
993
|
+
var _a, _b, _c;
|
|
994
|
+
throwIfAborted(options.signal);
|
|
995
|
+
const name = getWorkerName(worker);
|
|
996
|
+
const workerFarm = WorkerFarm.getWorkerFarm(options);
|
|
997
|
+
const workerPool = workerFarm.getWorkerPool(getWorkerPoolTarget(worker, options, name));
|
|
998
|
+
const outputBatches = new AsyncQueue();
|
|
999
|
+
const inputIterator = getAsyncIterator(input);
|
|
1000
|
+
let outputFinished = false;
|
|
1001
|
+
let inputFinished = false;
|
|
1002
|
+
let inputRequest = Promise.resolve();
|
|
1003
|
+
const batchJobFailed = new Error("Worker batch job failed");
|
|
1004
|
+
const finishOutput = () => {
|
|
1005
|
+
if (!outputFinished) {
|
|
1006
|
+
outputFinished = true;
|
|
1007
|
+
outputBatches.close();
|
|
1008
|
+
}
|
|
1009
|
+
};
|
|
1010
|
+
const failOutput = (_error) => {
|
|
1011
|
+
if (!outputFinished) {
|
|
1012
|
+
outputFinished = true;
|
|
1013
|
+
outputBatches.enqueue(batchJobFailed);
|
|
1014
|
+
outputBatches.close();
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
const job = await workerPool.startJob(
|
|
1018
|
+
options.jobName || worker.name,
|
|
1019
|
+
(activeJob, type, payload) => {
|
|
1020
|
+
switch (type) {
|
|
1021
|
+
case "input-request":
|
|
1022
|
+
inputRequest = inputRequest.then(async () => {
|
|
1023
|
+
const nextBatch = await inputIterator.next();
|
|
1024
|
+
if (!activeJob.isRunning) {
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
if (nextBatch.done) {
|
|
1028
|
+
inputFinished = true;
|
|
1029
|
+
activeJob.postMessage("input-done", {});
|
|
1030
|
+
} else {
|
|
1031
|
+
activeJob.postMessage("input-batch", { input: nextBatch.value });
|
|
1032
|
+
}
|
|
1033
|
+
}).catch((error) => activeJob.abort(error));
|
|
1034
|
+
break;
|
|
1035
|
+
case "output-batch":
|
|
1036
|
+
outputBatches.push(payload.result);
|
|
1037
|
+
break;
|
|
1038
|
+
case "done":
|
|
1039
|
+
activeJob.done(payload);
|
|
1040
|
+
finishOutput();
|
|
1041
|
+
break;
|
|
1042
|
+
case "error": {
|
|
1043
|
+
const error = new Error(payload.error || "Worker batch processing failed");
|
|
1044
|
+
activeJob.error(error);
|
|
1045
|
+
failOutput(error);
|
|
1046
|
+
break;
|
|
1047
|
+
}
|
|
1048
|
+
case "process":
|
|
1049
|
+
void onMessage(context, activeJob, type, payload);
|
|
1050
|
+
break;
|
|
1051
|
+
default: {
|
|
1052
|
+
const error = new Error(`Unexpected worker batch message: ${type}`);
|
|
1053
|
+
activeJob.error(error);
|
|
1054
|
+
failOutput(error);
|
|
1055
|
+
break;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
);
|
|
1060
|
+
const abortJob = () => job.abort(getAbortReason(options.signal));
|
|
1061
|
+
(_a = options.signal) == null ? void 0 : _a.addEventListener("abort", abortJob, { once: true });
|
|
1062
|
+
if ((_b = options.signal) == null ? void 0 : _b.aborted) {
|
|
1063
|
+
abortJob();
|
|
1064
|
+
}
|
|
1065
|
+
void job.result.catch(failOutput);
|
|
1066
|
+
try {
|
|
1067
|
+
const { signal: _signal, ...workerOptions } = options;
|
|
1068
|
+
if (job.isRunning) {
|
|
1069
|
+
job.postMessage("process-in-batches", {
|
|
1070
|
+
options: getTransferListForWriter(workerOptions),
|
|
1071
|
+
context: getTransferListForWriter(jobContext)
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
try {
|
|
1075
|
+
for await (const outputBatch of outputBatches) {
|
|
1076
|
+
yield outputBatch;
|
|
1077
|
+
if (job.isRunning) {
|
|
1078
|
+
job.postMessage("output-ack", {});
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
} catch (error) {
|
|
1082
|
+
if (error === batchJobFailed) {
|
|
1083
|
+
await job.result;
|
|
1084
|
+
}
|
|
1085
|
+
throw error;
|
|
1086
|
+
}
|
|
1087
|
+
await job.result;
|
|
1088
|
+
} finally {
|
|
1089
|
+
(_c = options.signal) == null ? void 0 : _c.removeEventListener("abort", abortJob);
|
|
1090
|
+
if (job.isRunning) {
|
|
1091
|
+
job.abort(createAbortError2("Worker batch iterator was closed"));
|
|
1092
|
+
}
|
|
1093
|
+
if (!inputFinished) {
|
|
1094
|
+
closeInputIterator(inputIterator);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
847
1098
|
function throwIfAborted(signal) {
|
|
848
1099
|
if (!(signal == null ? void 0 : signal.aborted)) {
|
|
849
1100
|
return;
|
|
@@ -858,6 +1109,39 @@ function createAbortError2(message) {
|
|
|
858
1109
|
error.name = "AbortError";
|
|
859
1110
|
return error;
|
|
860
1111
|
}
|
|
1112
|
+
function getAsyncIterator(input) {
|
|
1113
|
+
if (Symbol.asyncIterator in input) {
|
|
1114
|
+
return input[Symbol.asyncIterator]();
|
|
1115
|
+
}
|
|
1116
|
+
return (async function* iterateSynchronously() {
|
|
1117
|
+
yield* input;
|
|
1118
|
+
})();
|
|
1119
|
+
}
|
|
1120
|
+
function closeInputIterator(inputIterator) {
|
|
1121
|
+
var _a;
|
|
1122
|
+
try {
|
|
1123
|
+
void Promise.resolve((_a = inputIterator.return) == null ? void 0 : _a.call(inputIterator)).catch(() => void 0);
|
|
1124
|
+
} catch {
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
function getWorkerPoolTarget(worker, options, name) {
|
|
1128
|
+
if (options.source) {
|
|
1129
|
+
return { name, source: options.source };
|
|
1130
|
+
}
|
|
1131
|
+
const customWorkerUrl = getCustomWorkerURL(worker, options);
|
|
1132
|
+
if (customWorkerUrl) {
|
|
1133
|
+
return { name, url: customWorkerUrl };
|
|
1134
|
+
}
|
|
1135
|
+
if (isBrowser2 && worker.loadWorker) {
|
|
1136
|
+
return {
|
|
1137
|
+
name,
|
|
1138
|
+
loadWorker: worker.loadWorker,
|
|
1139
|
+
getUrl: () => getWorkerURL(worker, options),
|
|
1140
|
+
urlKey: getDefaultWorkerURL(worker)
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
return { name, url: getWorkerURL(worker, options) };
|
|
1144
|
+
}
|
|
861
1145
|
async function onMessage(context, job, type, payload) {
|
|
862
1146
|
switch (type) {
|
|
863
1147
|
case "done":
|
|
@@ -897,13 +1181,13 @@ function validateWorkerVersion(worker, coreVersion = VERSION2) {
|
|
|
897
1181
|
|
|
898
1182
|
// ../loader-utils/src/lib/worker-loader-utils/parse-with-worker.ts
|
|
899
1183
|
function canParseWithWorker(loader, options) {
|
|
900
|
-
var _a
|
|
1184
|
+
var _a;
|
|
901
1185
|
const workerOptions = getWorkerOptions(options);
|
|
902
1186
|
const nodeWorkers = workerOptions._nodeWorkers;
|
|
903
1187
|
if (!isBrowser2 && !nodeWorkers) {
|
|
904
1188
|
return false;
|
|
905
1189
|
}
|
|
906
|
-
if (loader.id === "
|
|
1190
|
+
if (loader.id === "las" && (((_a = options == null ? void 0 : options.las) == null ? void 0 : _a.shape) ?? "arrow-table") === "arrow-table") {
|
|
907
1191
|
return false;
|
|
908
1192
|
}
|
|
909
1193
|
if (loader.id === "csv" && !shouldParseCSVWithWorker(options)) {
|
|
@@ -911,12 +1195,30 @@ function canParseWithWorker(loader, options) {
|
|
|
911
1195
|
}
|
|
912
1196
|
return Boolean(canProcessOnWorker(loader, workerOptions));
|
|
913
1197
|
}
|
|
1198
|
+
function shouldParseWithWorker(loader, data, options, context, estimateLoader = loader) {
|
|
1199
|
+
var _a, _b;
|
|
1200
|
+
if (!canParseWithWorker(loader, options)) {
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
if (((_a = options == null ? void 0 : options.core) == null ? void 0 : _a.worker) !== "auto" || !estimateLoader.getWorkerEstimate) {
|
|
1204
|
+
return true;
|
|
1205
|
+
}
|
|
1206
|
+
try {
|
|
1207
|
+
const estimate = estimateLoader.getWorkerEstimate(data, options, context);
|
|
1208
|
+
if (estimate === void 0 || !Number.isFinite(estimate) || estimate < 0 || estimate > 1) {
|
|
1209
|
+
return true;
|
|
1210
|
+
}
|
|
1211
|
+
return estimate >= (((_b = options.core) == null ? void 0 : _b.workerThreshold) ?? 0.1);
|
|
1212
|
+
} catch {
|
|
1213
|
+
return true;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
914
1216
|
async function parseWithWorker(loader, data, options, context, parseOnMainThread, signal) {
|
|
915
1217
|
const workerSignal = signal || getWorkerAbortSignal(options);
|
|
916
1218
|
const result = await processOnWorker(
|
|
917
1219
|
loader,
|
|
918
1220
|
data,
|
|
919
|
-
{ ...getWorkerOptions(options), signal: workerSignal },
|
|
1221
|
+
{ ...getWorkerOptions(options, loader), signal: workerSignal },
|
|
920
1222
|
{
|
|
921
1223
|
process: async (input, processOptions, _workerContext, parseContext) => {
|
|
922
1224
|
if (!parseOnMainThread) {
|
|
@@ -935,6 +1237,32 @@ async function parseWithWorker(loader, data, options, context, parseOnMainThread
|
|
|
935
1237
|
);
|
|
936
1238
|
return isLoaderWithWorkerResultDeserializer(loader) ? loader.deserializeWorkerResult(result, options, context) : result;
|
|
937
1239
|
}
|
|
1240
|
+
async function* parseWithWorkerInBatches(loader, inputIterator, options, context, parseOnMainThread, signal) {
|
|
1241
|
+
const workerSignal = signal || getWorkerAbortSignal(options);
|
|
1242
|
+
const outputIterator = processOnWorkerInBatches(
|
|
1243
|
+
loader,
|
|
1244
|
+
inputIterator,
|
|
1245
|
+
{ ...getWorkerOptions(options), signal: workerSignal },
|
|
1246
|
+
{
|
|
1247
|
+
process: async (input, processOptions, _workerContext, parseContext) => {
|
|
1248
|
+
if (!parseOnMainThread) {
|
|
1249
|
+
throw new Error("Worker not set up to parse on main thread");
|
|
1250
|
+
}
|
|
1251
|
+
const mainThreadContext = context ? { ...context, ...parseContext || {} } : void 0;
|
|
1252
|
+
return await callParseOnMainThread(
|
|
1253
|
+
parseOnMainThread,
|
|
1254
|
+
input,
|
|
1255
|
+
processOptions,
|
|
1256
|
+
mainThreadContext
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
},
|
|
1260
|
+
getSerializableLoaderContext(context)
|
|
1261
|
+
);
|
|
1262
|
+
for await (const batch of outputIterator) {
|
|
1263
|
+
yield loader.deserializeWorkerBatch ? loader.deserializeWorkerBatch(batch, options, context) : batch;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
938
1266
|
function getWorkerAbortSignal(options) {
|
|
939
1267
|
var _a;
|
|
940
1268
|
const parquetSignal = (_a = options == null ? void 0 : options.parquet) == null ? void 0 : _a.signal;
|
|
@@ -949,12 +1277,19 @@ function callParseOnMainThread(parseOnMainThread, input, options, context) {
|
|
|
949
1277
|
}
|
|
950
1278
|
return parseOnMainThread(input, void 0, options, context);
|
|
951
1279
|
}
|
|
952
|
-
function getWorkerOptions(options = {}) {
|
|
1280
|
+
function getWorkerOptions(options = {}, loader) {
|
|
953
1281
|
const serializedOptions = JSON.parse(JSON.stringify(options));
|
|
954
|
-
|
|
1282
|
+
const workerOptions = {
|
|
955
1283
|
...serializedOptions.core,
|
|
956
1284
|
...serializedOptions
|
|
957
1285
|
};
|
|
1286
|
+
if (workerOptions.worker === "auto") {
|
|
1287
|
+
workerOptions.worker = true;
|
|
1288
|
+
}
|
|
1289
|
+
if (loader) {
|
|
1290
|
+
workerOptions._workerLoaderId = loader.id;
|
|
1291
|
+
}
|
|
1292
|
+
return workerOptions;
|
|
958
1293
|
}
|
|
959
1294
|
function getSerializableLoaderContext(context) {
|
|
960
1295
|
if (!context) {
|
|
@@ -2029,6 +2364,7 @@ var DEFAULT_LOADER_OPTIONS = {
|
|
|
2029
2364
|
CDN: "https://unpkg.com/@loaders.gl",
|
|
2030
2365
|
worker: true,
|
|
2031
2366
|
// By default, use worker if provided by loader.
|
|
2367
|
+
workerThreshold: 0.1,
|
|
2032
2368
|
maxConcurrency: 3,
|
|
2033
2369
|
// How many worker instances should be created for each loader.
|
|
2034
2370
|
maxMobileConcurrency: 1,
|
|
@@ -2104,6 +2440,7 @@ var CORE_LOADER_OPTION_KEYS = [
|
|
|
2104
2440
|
"useLocalLibraries",
|
|
2105
2441
|
"CDN",
|
|
2106
2442
|
"worker",
|
|
2443
|
+
"workerThreshold",
|
|
2107
2444
|
"maxConcurrency",
|
|
2108
2445
|
"maxMobileConcurrency",
|
|
2109
2446
|
"reuseWorkers",
|
|
@@ -2144,7 +2481,10 @@ function normalizeOptions(options, loader, loaders, url) {
|
|
|
2144
2481
|
loaders = loaders || [];
|
|
2145
2482
|
loaders = Array.isArray(loaders) ? loaders : [loaders];
|
|
2146
2483
|
validateOptions(options, loaders);
|
|
2147
|
-
|
|
2484
|
+
validateWorkerThreshold(options);
|
|
2485
|
+
const normalizedOptions = normalizeLoaderOptions(normalizeOptionsInternal(loader, options, url));
|
|
2486
|
+
validateWorkerThreshold(normalizedOptions);
|
|
2487
|
+
return normalizedOptions;
|
|
2148
2488
|
}
|
|
2149
2489
|
function normalizeLoaderOptions(options) {
|
|
2150
2490
|
const normalized = cloneLoaderOptions(options);
|
|
@@ -2168,6 +2508,13 @@ function validateOptions(options, loaders) {
|
|
|
2168
2508
|
validateOptionsObject(idOptions, loader.id, loaderOptions, deprecatedOptions, loaders);
|
|
2169
2509
|
}
|
|
2170
2510
|
}
|
|
2511
|
+
function validateWorkerThreshold(options) {
|
|
2512
|
+
var _a;
|
|
2513
|
+
const threshold = (_a = options.core) == null ? void 0 : _a.workerThreshold;
|
|
2514
|
+
if (threshold !== void 0 && (!Number.isFinite(threshold) || threshold < 0 || threshold > 1)) {
|
|
2515
|
+
throw new Error("core.workerThreshold must be a finite number between 0 and 1");
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2171
2518
|
function validateOptionsObject(options, id, defaultOptions, deprecatedOptions, loaders) {
|
|
2172
2519
|
const loaderName = id || "Top level";
|
|
2173
2520
|
const prefix = id ? `${id}.` : "";
|
|
@@ -2872,7 +3219,8 @@ function getFetchFunction(options, context) {
|
|
|
2872
3219
|
if (typeof fetchOption === "function") {
|
|
2873
3220
|
fetchFunction = fetchOption;
|
|
2874
3221
|
} else if (isObject(fetchOption)) {
|
|
2875
|
-
|
|
3222
|
+
const baseFetch = (context == null ? void 0 : context.fetch) || fetchFile;
|
|
3223
|
+
fetchFunction = (url, requestOptions) => baseFetch(url, mergeFetchOptions(fetchOption, requestOptions));
|
|
2876
3224
|
} else if (context == null ? void 0 : context.fetch) {
|
|
2877
3225
|
fetchFunction = context.fetch;
|
|
2878
3226
|
} else {
|
|
@@ -3167,6 +3515,9 @@ async function parseToOutputIterator(loader, data, options, context) {
|
|
|
3167
3515
|
const inputIterator = await getAsyncIterableFromData(data, options);
|
|
3168
3516
|
const transformedIterator = await applyInputTransforms(inputIterator, ((_a = options == null ? void 0 : options.core) == null ? void 0 : _a.transforms) || []);
|
|
3169
3517
|
if (loader.parseInBatches) {
|
|
3518
|
+
if (loader.id === "csv" && isBrowser && canParseWithWorker(loader, options)) {
|
|
3519
|
+
return parseWithWorkerInBatches(loader, transformedIterator, options, context, parse);
|
|
3520
|
+
}
|
|
3170
3521
|
return loader.parseInBatches(transformedIterator, options, context);
|
|
3171
3522
|
}
|
|
3172
3523
|
return parseChunkInBatches(transformedIterator, loader, options, context);
|
|
@@ -3337,7 +3688,10 @@ var coreApi = Object.freeze({
|
|
|
3337
3688
|
// dist/lib/loader-utils/loader-context.js
|
|
3338
3689
|
function getLoaderContext(context, options, parentContext) {
|
|
3339
3690
|
if (parentContext) {
|
|
3340
|
-
return
|
|
3691
|
+
return {
|
|
3692
|
+
...parentContext,
|
|
3693
|
+
fetch: getFetchFunction(options, parentContext)
|
|
3694
|
+
};
|
|
3341
3695
|
}
|
|
3342
3696
|
const newContext = {
|
|
3343
3697
|
...context,
|
|
@@ -3408,7 +3762,7 @@ async function parseWithLoader(loader, data, options, context) {
|
|
|
3408
3762
|
context.response = { headers, ok, redirected, status, statusText, type, url };
|
|
3409
3763
|
}
|
|
3410
3764
|
const loaderWithParser = await getLoaderImplementation(loader, options, context.url);
|
|
3411
|
-
if (
|
|
3765
|
+
if (shouldParseWithWorker(loaderWithParser, data, options, context, loader)) {
|
|
3412
3766
|
data = await getArrayBufferFromData(data, options);
|
|
3413
3767
|
return await parseWithWorker(loaderWithParser, data, options, context, parse);
|
|
3414
3768
|
}
|
|
@@ -3651,7 +4005,7 @@ function makeStream(source, options) {
|
|
|
3651
4005
|
}
|
|
3652
4006
|
|
|
3653
4007
|
// dist/null-loader.js
|
|
3654
|
-
var VERSION4 = true ? "5.0.0-alpha.
|
|
4008
|
+
var VERSION4 = true ? "5.0.0-alpha.7" : "latest";
|
|
3655
4009
|
var NullWorkerLoader = {
|
|
3656
4010
|
dataType: null,
|
|
3657
4011
|
batchType: null,
|