bruce-models 7.1.102 → 7.1.103

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.
@@ -12813,6 +12813,185 @@ class DelayQueue {
12813
12813
  }
12814
12814
  }
12815
12815
 
12816
+ /**
12817
+ * Runs work that several callers keep asking for, at a rate the answer can actually arrive at.
12818
+ */
12819
+ var RequestLane;
12820
+ (function (RequestLane) {
12821
+ RequestLane.DISPOSED = "RequestLane disposed";
12822
+ RequestLane.TIMED_OUT = "RequestLane timed out";
12823
+ /**
12824
+ * A set of independently rate-limited keys.
12825
+ * One per subject, eg. one lane for Entity reads with the Entity ID as the key.
12826
+ */
12827
+ class Lane {
12828
+ constructor(options = {}) {
12829
+ this.options = options;
12830
+ this.pending = new Map();
12831
+ this.inFlight = new Set();
12832
+ this.lastStarted = new Map();
12833
+ this.timers = new Map();
12834
+ // Keys with a pump owed at the end of this turn.
12835
+ this.scheduled = new Set();
12836
+ this.disposed = false;
12837
+ }
12838
+ /**
12839
+ * Asks for this work to be run for this key, and resolves with whatever run answers for it.
12840
+ * @param key what is being asked about, eg: an Entity ID.
12841
+ * @param work how to find out.
12842
+ */
12843
+ Run(key, work) {
12844
+ if (this.disposed) {
12845
+ return Promise.reject(new Error(RequestLane.DISPOSED));
12846
+ }
12847
+ return new Promise((resolve, reject) => {
12848
+ const slot = this.pending.get(key);
12849
+ if (slot) {
12850
+ // Newest wins: the older work has been overtaken, but whoever asked for it is
12851
+ // still owed an answer, so their waiter stays.
12852
+ slot.work = work;
12853
+ slot.waiters.push({ resolve, reject });
12854
+ }
12855
+ else {
12856
+ this.pending.set(key, { work, waiters: [{ resolve, reject }] });
12857
+ }
12858
+ this.schedulePump(key);
12859
+ });
12860
+ }
12861
+ /**
12862
+ * Whether a run is currently out for this key.
12863
+ */
12864
+ IsRunning(key) {
12865
+ return this.inFlight.has(key);
12866
+ }
12867
+ /**
12868
+ * How long this key must wait before it may run again, zero when it may run now.
12869
+ */
12870
+ WaitFor(key) {
12871
+ const minInterval = this.options.minIntervalMs || 0;
12872
+ if (!minInterval) {
12873
+ return 0;
12874
+ }
12875
+ const last = this.lastStarted.get(key);
12876
+ if (last == null) {
12877
+ return 0;
12878
+ }
12879
+ const now = (this.options.now || Date.now)();
12880
+ return Math.max(0, (last + minInterval) - now);
12881
+ }
12882
+ /**
12883
+ * Forgets a key, answering whatever was waiting on it. For a caller that has gone away.
12884
+ * @param key
12885
+ */
12886
+ Drop(key) {
12887
+ const timer = this.timers.get(key);
12888
+ if (timer != null) {
12889
+ clearTimeout(timer);
12890
+ this.timers.delete(key);
12891
+ }
12892
+ const slot = this.pending.get(key);
12893
+ if (slot) {
12894
+ this.pending.delete(key);
12895
+ this.rejectAll(slot, new Error(RequestLane.DISPOSED));
12896
+ }
12897
+ }
12898
+ Dispose() {
12899
+ this.disposed = true;
12900
+ for (const timer of Array.from(this.timers.values())) {
12901
+ clearTimeout(timer);
12902
+ }
12903
+ this.timers.clear();
12904
+ this.scheduled.clear();
12905
+ for (const slot of Array.from(this.pending.values())) {
12906
+ this.rejectAll(slot, new Error(RequestLane.DISPOSED));
12907
+ }
12908
+ this.pending.clear();
12909
+ this.inFlight.clear();
12910
+ this.lastStarted.clear();
12911
+ }
12912
+ /*
12913
+ * Answers every waiter on a slot with the same failure.
12914
+ */
12915
+ rejectAll(slot, error) {
12916
+ for (const waiter of slot.waiters) {
12917
+ waiter.reject(error);
12918
+ }
12919
+ }
12920
+ /*
12921
+ * Runs the pump at the end of this turn rather than during it.
12922
+ */
12923
+ schedulePump(key) {
12924
+ if (this.disposed || this.scheduled.has(key)) {
12925
+ return;
12926
+ }
12927
+ this.scheduled.add(key);
12928
+ Promise.resolve().then(() => {
12929
+ this.scheduled.delete(key);
12930
+ this.pump(key);
12931
+ });
12932
+ }
12933
+ /*
12934
+ * Starts the next run for a key when it has one and is allowed to.
12935
+ */
12936
+ pump(key) {
12937
+ if (this.disposed || this.inFlight.has(key) || !this.pending.has(key)) {
12938
+ return;
12939
+ }
12940
+ const waitFor = this.WaitFor(key);
12941
+ if (waitFor > 0) {
12942
+ // Whatever else is asked for during the wait folds into the same slot, so the run
12943
+ // that eventually goes is the newest one rather than the one that started the wait.
12944
+ if (!this.timers.has(key)) {
12945
+ this.timers.set(key, setTimeout(() => {
12946
+ this.timers.delete(key);
12947
+ this.pump(key);
12948
+ }, waitFor));
12949
+ }
12950
+ return;
12951
+ }
12952
+ const slot = this.pending.get(key);
12953
+ this.pending.delete(key);
12954
+ this.inFlight.add(key);
12955
+ this.lastStarted.set(key, (this.options.now || Date.now)());
12956
+ let settled = false;
12957
+ const finish = (settle) => {
12958
+ if (settled) {
12959
+ return;
12960
+ }
12961
+ settled = true;
12962
+ this.inFlight.delete(key);
12963
+ settle();
12964
+ if (!this.disposed) {
12965
+ this.schedulePump(key);
12966
+ }
12967
+ };
12968
+ const timeoutMs = this.options.timeoutMs || 0;
12969
+ let timeout = null;
12970
+ if (timeoutMs > 0) {
12971
+ timeout = setTimeout(() => finish(() => this.rejectAll(slot, new Error(RequestLane.TIMED_OUT))), timeoutMs);
12972
+ }
12973
+ // Wrapped rather than called directly, so work that throws before returning a promise is
12974
+ // a rejection like any other rather than something that leaves the key held forever.
12975
+ Promise.resolve().then(slot.work).then((value) => {
12976
+ if (timeout != null) {
12977
+ clearTimeout(timeout);
12978
+ }
12979
+ finish(() => {
12980
+ for (const waiter of slot.waiters) {
12981
+ waiter.resolve(value);
12982
+ }
12983
+ });
12984
+ }, (error) => {
12985
+ if (timeout != null) {
12986
+ clearTimeout(timeout);
12987
+ }
12988
+ finish(() => this.rejectAll(slot, error));
12989
+ });
12990
+ }
12991
+ }
12992
+ RequestLane.Lane = Lane;
12993
+ })(RequestLane || (RequestLane = {}));
12994
+
12816
12995
  /**
12817
12996
  * Describes a Bruce stored date.
12818
12997
  */
@@ -24111,7 +24290,7 @@ function getFirstWrappedArray(data, wrapperKeys) {
24111
24290
  }
24112
24291
 
24113
24292
  // This is updated with the package.json version on build.
24114
- const VERSION = "7.1.102";
24293
+ const VERSION = "7.1.103";
24115
24294
 
24116
- export { VERSION, Account, AccountAudit, AccountConcept, AccountFeatures, AccountInvite, AccountLimits, AccountTemplate, AccountType, AnnDocument, AbstractApi, Api, ApiGetters, BruceApi, GlobalApi, GuardianApi, Assembly, Calculator, ChangeSet, ClientFile, ClientFileValueMap, Bounds, BruceEvent, BruceVariable, CacheControl, Camera, Cartes, Carto, Color, DelayQueue, GeoJson, Geometry, LRUCache, UTC, CustomForm, DashboardView, DataFeed, DataLab, DataLabGroup, DataSource, DataTransform, Comment, Entity, EntityAttachment, EntityAttachmentType, EntityAttribute, EntityComment, EntityCoords, EntityHistoricData, EntityLink, EntityLod, EntityLodCategory, EntityRelation, EntityRelationType, EntitySource, EntityTableView, EntityTag, EntityType, EntityTypeRelation, EntityTypeTrigger, Ontology, OntologyDocument, ENVIRONMENT, ExportBrz, ExportCsv, ExportNsx, ExportUsd, Hexbin, ImportAssembly, ImportCad, ImportCsv, ImportGeoJson, ImportJson, ImportKml, ImportLcc, ImportTif, ImportedFile, Uploader, Markup, UIMarkup, NAVIGATOR_CHAT_EVENT_ENTITY_HIGHLIGHT_APPLIED, NAVIGATOR_CHAT_EVENT_SCENE_CONTEXT_PREFETCHED, NavigatorChatClient, NavigatorMcpWebSocketClient, Plugin, PluginAiTool, ProgramKey, MenuItem, ProjectView, ProjectViewBookmark, ProjectViewBookmarkGroup, ProjectViewLegacy, ProjectViewLegacyBookmark, ProjectViewLegacyTile, ProjectViewTile, ZoomControl, Scenario, HostingLocation, MessageBroker, PendingAction, RecordChangeFeed, Style, Tileset, Tracking, Permission, Session, User, UserGroup, UserMfaMethod, EncryptUtils, MathUtils, ObjectUtils, PathUtils, UrlUtils, WorkflowType, WorkflowItemType };
24295
+ export { VERSION, Account, AccountAudit, AccountConcept, AccountFeatures, AccountInvite, AccountLimits, AccountTemplate, AccountType, AnnDocument, AbstractApi, Api, ApiGetters, BruceApi, GlobalApi, GuardianApi, Assembly, Calculator, ChangeSet, ClientFile, ClientFileValueMap, Bounds, BruceEvent, BruceVariable, CacheControl, Camera, Cartes, Carto, Color, DelayQueue, RequestLane, GeoJson, Geometry, LRUCache, UTC, CustomForm, DashboardView, DataFeed, DataLab, DataLabGroup, DataSource, DataTransform, Comment, Entity, EntityAttachment, EntityAttachmentType, EntityAttribute, EntityComment, EntityCoords, EntityHistoricData, EntityLink, EntityLod, EntityLodCategory, EntityRelation, EntityRelationType, EntitySource, EntityTableView, EntityTag, EntityType, EntityTypeRelation, EntityTypeTrigger, Ontology, OntologyDocument, ENVIRONMENT, ExportBrz, ExportCsv, ExportNsx, ExportUsd, Hexbin, ImportAssembly, ImportCad, ImportCsv, ImportGeoJson, ImportJson, ImportKml, ImportLcc, ImportTif, ImportedFile, Uploader, Markup, UIMarkup, NAVIGATOR_CHAT_EVENT_ENTITY_HIGHLIGHT_APPLIED, NAVIGATOR_CHAT_EVENT_SCENE_CONTEXT_PREFETCHED, NavigatorChatClient, NavigatorMcpWebSocketClient, Plugin, PluginAiTool, ProgramKey, MenuItem, ProjectView, ProjectViewBookmark, ProjectViewBookmarkGroup, ProjectViewLegacy, ProjectViewLegacyBookmark, ProjectViewLegacyTile, ProjectViewTile, ZoomControl, Scenario, HostingLocation, MessageBroker, PendingAction, RecordChangeFeed, Style, Tileset, Tracking, Permission, Session, User, UserGroup, UserMfaMethod, EncryptUtils, MathUtils, ObjectUtils, PathUtils, UrlUtils, WorkflowType, WorkflowItemType };
24117
24296
  //# sourceMappingURL=bruce-models.es5.js.map