From e875765cf6bec218b964c88eb1e85e48def388c1 Mon Sep 17 00:00:00 2001 From: tejaede Date: Mon, 1 Jun 2026 11:48:59 -0500 Subject: [PATCH 1/6] Add event/operation history + serialized handling - Add Event.dispatchChain so an event is aware when it is dispatched as part of the handling of another. - Add a ReadCompletedOperation as the referrer to ReadOperations created while mapping the data returned by that ReadCompletedOperation - Prevent 2 unrelated events of the same type from being handled simultaneously. For example, a second ReadOperation event can only be handled if it is necessary to complete the handling of another in-progress ReadOperation - Fix issue where ReadOperation.propagationPromise was not being resolved --- core/event/change-event.js | 4 + core/event/event-manager.js | 94 ++++++++++++++++++- core/event/mutable-event.js | 27 +++++- .../raw-foreign-value-to-object-converter.js | 40 ++++++-- data/model/data-event.js | 5 + data/service/data-operation.js | 66 +++++++++++-- data/service/data-service.js | 29 ++++++ data/service/http-service.js | 2 + data/service/raw-data-service.js | 9 ++ 9 files changed, 258 insertions(+), 18 deletions(-) diff --git a/core/event/change-event.js b/core/event/change-event.js index 194df6afc..a51c1e329 100644 --- a/core/event/change-event.js +++ b/core/event/change-event.js @@ -177,6 +177,10 @@ var ChangeEvent = exports.ChangeEvent = Montage.specialize({ */ removedValues: { value: undefined + }, + + tracksDispatchChain: { + value: true } }); diff --git a/core/event/event-manager.js b/core/event/event-manager.js index 5aacf9ddf..f9b741cd6 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -3238,11 +3238,65 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } }, + _activeEventsByType: { + get: function () { + return this.__activeEventsByType || (this.__activeEventsByType = new Map()); + } + }, + + _eventQueueByType: { + get: function () { + return this.__eventQueueByType || (this.__eventQueueByType = new Map()); + } + }, + + handleEvent: { + enumerable: false, + value: function (event) { + + if (this._activeEventsByType.has(event.type) && !this._hasActiveReferrer(event)) { + if (!this._eventQueueByType.has(event.type)) { + this._eventQueueByType.set(event.type, []); + } + this._eventQueueByType.get(event.type).unshift(event); + } else if (!this._activeEventsByType.has(event.type)) { + this._activeEventsByType.set(event.type, new Set([event])); + this._handleEvent(event); + } else { + this._activeEventsByType.get(event.type).add(event); + this._handleEvent(event); + } + } + }, + + _hasActiveReferrer: { + value: function (event) { + let referrer; + if (event.referrer) { + return this._isActive(event.referrer); + } else if (event.referrers) { + let i, n, isActive; + for (i = 0, n = event.referrers.length; i < n && !isActive; ++i) { + isActive = this._isActive(event.referrers[i]); + } + return isActive; + } + return false; + } + }, + + _isActive: { + value: function (event) { + let activeByType = this._activeEventsByType.get(event.type); + return !!activeByType && activeByType.has(event); + } + }, + /** @function @param {Event} event The handled event. */ - handleEvent: { + _handleEvent: { enumerable: false, value: function EventManager_handleEvent(event) { // if(event.type === "pointerdown" || event.type === "pointerup" || event.type.indexOf("press") !== -1) { @@ -3264,6 +3318,20 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan targetEntry, targetEntryForEventType, promise; + if (event.tracksDispatchChain) { + if (this._previousEvent && this._previousEvent.dispatchChain && this._previousEvent.dispatchChain.length && event.dispatchChain) { + // console.log(`[EventManager] Mark Event ${event.target.objectDescriptor.name}`); + event.dispatchChain.push.apply(event.dispatchChain, this._previousEvent.dispatchChain); + event.dispatchChain.push(this._previousEvent); + } else if (this._previousEvent && event.dispatchChain) { + // console.log(`[EventManager] Push Previous Event ${event.target.objectDescriptor.name}`); + event.dispatchChain.push(this._previousEvent); + } else { + // console.log(`[EventManager] Record initial event ${event.target.objectDescriptor.name}`); + } + this._previousEvent = event; + } + if(this.isBrowser) { if( (MontageElement && event.target instanceof MontageElement) || @@ -3400,6 +3468,30 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } } + //Handle next event + let type = mutableEvent.type, + next; + if (this._eventQueueByType.has(type) && this._eventQueueByType.get(type).length) { + next = this._eventQueueByType.get(type).pop(); + this._activeEventsByType.get(type).delete(event); + this._activeEventsByType.get(type).add(next); + this._handleEvent(next); + } else { + this._activeEventsByType.delete(type); + this._eventQueueByType.delete(type); + } + + if (this._previousEvent === event || this._previousEvent === mutableEvent) { + this._previousEvent = event.dispatchChain[event.dispatchChain.length - 1]; + let name = event.target.name || event.target.objectDescriptor.name, + previousName; + if (this._previousEvent) { + previousName = this._previousEvent.target.name || this._previousEvent.target.objectDescriptor.name; + console.log(`[EventManager] Reset previous event ${event.identifier} ${name} ${event.type} to ${this._previousEvent.identifier} ${previousName} ${this._previousEvent.type}`); + } else { + console.log(`[EventManager] Clear previous event ${event.identifier} ${name} ${event.type}`); + } + } } }, diff --git a/core/event/mutable-event.js b/core/event/mutable-event.js index 0e414b1ac..b379f3ed9 100644 --- a/core/event/mutable-event.js +++ b/core/event/mutable-event.js @@ -394,12 +394,37 @@ var wrapPropertyGetter = function (key, storageKey) { }, /** * @type {Property} - * @default {Element} null + * @default {Array} null */ composedPath: { value: function () { return this._composedPath; } + }, + + /** + * @type {Property} + * @default {Array} null + * An ordered array containing the chain of events that led to the + * dispatch of this one + */ + dispatchChain: { + get: function () { + return this.tracksDispatchChain ? this._dispatchChain || (this._dispatchChain = []) : null; + } + }, + + /** + * @type {Property} + * @default {Boolean} false + * Indicates whether the ancestory if this event will be tracked. It is expensive + * so this is only set to true for clearly defined use cases + */ + tracksDispatchChain: { + // value: false + get: function () { + return (this._tracksDispatchChain !== void 0) ? this._tracksDispatchChain : (this._event && this._event.tracksDispatchChain); + } } }, { diff --git a/data/converter/raw-foreign-value-to-object-converter.js b/data/converter/raw-foreign-value-to-object-converter.js index 6ab19dc73..6b8e505c9 100644 --- a/data/converter/raw-foreign-value-to-object-converter.js +++ b/data/converter/raw-foreign-value-to-object-converter.js @@ -1,10 +1,12 @@ var RawValueToObjectConverter = require("./raw-value-to-object-converter").RawValueToObjectConverter, Criteria = require("../../core/criteria").Criteria, + DataOperation = require("../service/data-operation").DataOperation, DataQuery = require("../model/data-query").DataQuery, Map = require("../../core/collections/map").Map, syntaxProperties = require("../../core/frb/syntax-properties"), Uuid = require("core/uuid").Uuid, Promise = require("../../core/promise").Promise; + /** * @class RawForeignValueToObjectConverter * @classdesc Converts a property value of raw data to the referenced object. @@ -122,7 +124,7 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( } }, _fetchConvertedDataForObjectDescriptorCriteria: { - value: function(typeToFetch, criteria, currentRule, registerMappedPropertiesAsChanged) { + value: function(typeToFetch, criteria, currentRule, registerMappedPropertiesAsChanged, referrerOperation) { var self = this; return this.service ? this.service.then(function (service) { @@ -208,6 +210,10 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( query.hints = {rawDataService: service}; + if (referrerOperation) { + query.hints.referrerOperation = referrerOperation; + } + if(registerMappedPropertiesAsChanged){ query.hints.registerMappedPropertiesAsChanged = registerMappedPropertiesAsChanged; } @@ -351,12 +357,16 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( if(!queryParts) { queryParts = { criteria: [], - readExpressions: []/*, + readExpressions: [], + referrerOperations: []/*, hints: {}*/ }; self._pendingCriteriaByTypeToCombine.set(typeToFetch, queryParts); } queryParts.criteria.push(criteria); + if (referrerOperation) { + queryParts.referrerOperations.push(referrerOperation); + } /* Sounds twisted, but this is to deal with the case where we need to fetch to resolve a property of the object itself. @@ -495,6 +505,10 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( query.hints.registerMappedPropertiesAsChanged = registerMappedPropertiesAsChanged; } + if(queryParts.referrerOperations) { + query.hints.referrerOperations = queryParts.referrerOperations; + } + //console.log("_combineFetchDataMicrotaskFunctionForTypeQueryParts query:",query); mapIterationFetchPromise = rootService.fetchData(query) @@ -695,9 +709,23 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( value: Uuid.noValue }, + _findScopedDataOperation: { + value: function (scope) { + let operation; + while (scope.parent && !operation) { + if (scope.value instanceof DataOperation) { + operation = scope.value; + } + scope = scope.parent; + } + return operation; + } + }, + _convert: { value: function (scope, service) { - var v = scope.value; + var v = scope.value, + referrerOperation = this._findScopedDataOperation(scope); if((v && !(v instanceof Array )) || (v instanceof Array && v.length > 0)) { var self = this, //We put it in a local variable so we have the right value in the closure @@ -736,7 +764,7 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( aCriteria; while (anObjectDescriptor = mapIterator.next().value) { aCriteria = this.convertCriteriaForValue(groupMap.get(anObjectDescriptor)); - promises.push(this._fetchConvertedDataForObjectDescriptorCriteria(anObjectDescriptor, aCriteria, currentRule, registerMappedPropertiesAsChanged)); + promises.push(this._fetchConvertedDataForObjectDescriptorCriteria(anObjectDescriptor, aCriteria, currentRule, registerMappedPropertiesAsChanged, referrerOperation)); } @@ -763,7 +791,7 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( foreignKeyValue = v[rawDataProperty], aCriteria = this.convertCriteriaForValue(foreignKeyValue); - return this._fetchConvertedDataForObjectDescriptorCriteria(valueDescriptor, aCriteria, currentRule, registerMappedPropertiesAsChanged); + return this._fetchConvertedDataForObjectDescriptorCriteria(valueDescriptor, aCriteria, currentRule, registerMappedPropertiesAsChanged, referrerOperation); } else { return Promise.resolve(null); @@ -783,7 +811,7 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( return this._descriptorToFetch.then(function (typeToFetch) { - return self._fetchConvertedDataForObjectDescriptorCriteria(typeToFetch, criteria, currentRule, registerMappedPropertiesAsChanged); + return self._fetchConvertedDataForObjectDescriptorCriteria(typeToFetch, criteria, currentRule, registerMappedPropertiesAsChanged, referrerOperation); // if (self.serviceIdentifier) { // criteria.parameters.serviceIdentifier = self.serviceIdentifier; diff --git a/data/model/data-event.js b/data/model/data-event.js index 27b62c055..f96bb5124 100644 --- a/data/model/data-event.js +++ b/data/model/data-event.js @@ -58,6 +58,10 @@ exports.DataEvent = MutableEvent.specialize({ detail: { value: undefined + }, + + tracksDispatchChain: { + value: true } @@ -101,4 +105,5 @@ exports.DataEvent = MutableEvent.specialize({ value: "saveChangesProgress" } + }); diff --git a/data/service/data-operation.js b/data/service/data-operation.js index 7fc214580..923bc7bb7 100644 --- a/data/service/data-operation.js +++ b/data/service/data-operation.js @@ -655,6 +655,25 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM value: undefined }, + + + /************ + * Design Discussion 6/9/2026 + * + * 'referrer' and 'referrers' are needed in distinct use cases. We should make this explicit in + * one of two ways. + * 1. A class to encapsulate referrers e.g. OperationReferrer that can encapsulate 1 or + * more referrers. DataOperation.referrer would be an instance of this class + * + * 2. Subclasses of DataOperation that separate the use cases. One subclass would have referrer. + * The other would have referrers. + * Examples: + * - InitiatingReadOperation or RootReadOperation - A ReadOperation for a query sent from the app-level. No referrer property needed. + * - MergedReadOperation or NestedReadOperation - A ReadOperation for multiple merged queries. 'referrers' property + * - ReadCompletionOperation - A completion operation can only be associated to a single read. 'referrer' property + * + */ + /** * An operation that preceded and this one is related to. For a ReadUpdated, it would be the Read operation. * @@ -665,32 +684,55 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM }, referrer: { get: function() { - return this._referrer || ( - this._referrer === null - ? null - : (this._referrer = this?.rawDataService?.referrerForDataOperation(this)) - ); + if (this._referrer || this._referrer === null) { + return this._referrer; + } + + this._referrer = this?.rawDataService?.referrerForDataOperation(this); + if (this._referrer) { + this._referrer.referredOperations.push(this); + } + return this._referrer; }, set: function(value) { if(value !== this._referrer) { - this.referreredOperations.delete(this._referrer); + if (this._referrer) { + this._referrer.referredOperations.delete(this); + } this._referrer = value; - this.referreredOperations.push(this._referrer); + if (this._referrer) { + this._referrer.referredOperations.push(this); + } } } }, + referrers: { + get: function () { + return this._referrers; + }, + set: function (value) { + this._referrers = value; + if (Array.isArray(value)) { + value.forEach((referrer) => { + referrer.referredOperations.push(this); + }); + } + } + }, + + /** * inverse of referrer, an array of operations that has this as their referrer. * * @type {Array} */ - _referreredOperations: { + _referredOperations: { value: undefined }, - referreredOperations: { + referredOperations: { get: function() { - return this._referreredOperations || (this._referreredOperations = []); + return this._referredOperations || (this._referredOperations = []); } }, @@ -1093,6 +1135,10 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM } return this._objectDescriptors; } + }, + + tracksDispatchChain: { + value: true } diff --git a/data/service/data-service.js b/data/service/data-service.js index 210ffbf3a..e9b224b81 100644 --- a/data/service/data-service.js +++ b/data/service/data-service.js @@ -6620,7 +6620,14 @@ DataService.addClassProperties( if (query.hints) { readOperation.hints = query.hints; + if (query.hints.referrerOperation) { + readOperation.referrer = query.hints.referrerOperation; + } + if (query.hints.referrerOperations) { + readOperation.referrers = query.hints.referrerOperations; + } } + /* this is half-assed, we're mapping full objects to RawData, but not the properties in the expression. @@ -7228,6 +7235,7 @@ DataService.addClassProperties( - The snapshot may not help us since it could be a property resolved off the primary key if(trigger._getValueStatus(object) == ) + */ //Commentting out the restriction to exclude created objects as we might want to //use it for them as well @@ -7235,11 +7243,32 @@ DataService.addClassProperties( // if(!this._createdDataObjects || (this._createdDataObjects && !this._createdDataObjects.has(changeEvent.target))) { //Needs to register the change so saving changes / update operations can use it later to decise what to send //console.log("handleChange:",changeEvent); + if (changeEvent.dispatchChain.length > 0) { + // debugger; + // this._logEventChain(changeEvent); + } this.registerDataObjectChangesFromEvent(changeEvent); //} }, }, + _logEventChain: { + value: function (changeEvent) { + let name = changeEvent.target.name || changeEvent.target.objectDescriptor.name, + message = [ + `Change Event Tracking`, + `${changeEvent.identifier} ${name} ${changeEvent.type} --> ` + ]; + + changeEvent.dispatchChain.forEach((event) => { + message.push(`${event.identifier} ${event.target.name || event.target.objectDescriptor.name} ${event.type} --> `); + }); + + console.log(message.join("\n")); + + } + }, + /*************************************************************************** * Saving Data */ diff --git a/data/service/http-service.js b/data/service/http-service.js index b683a3bc4..c52ce6cf6 100644 --- a/data/service/http-service.js +++ b/data/service/http-service.js @@ -310,6 +310,8 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService tokenDataQuery.identity = resolvedIdentity; tokenQueryDataStream = this.mainService.fetchData(tokenDataQuery); + tokenDataQuery.hints = {referrerOperation: readOperation}; + return tokenQueryDataStream.then((result) => { if (result && result.length === 1) { let accessToken = result[0]; diff --git a/data/service/raw-data-service.js b/data/service/raw-data-service.js index 531180541..c4d5d29a0 100644 --- a/data/service/raw-data-service.js +++ b/data/service/raw-data-service.js @@ -3366,6 +3366,10 @@ RawDataService.addClassProperties({ unregisterPendingDataOperation: { value: function (dataOperation) { + let registration = this._pendingDataOperationById.get(dataOperation.id); + if (registration) { + registration.completionPromiseResolve(); + } this._pendingDataOperationById.delete(dataOperation.id); //Backup until bug fixed //DataService.mainService.unregisterDataStreamForDataOperation(dataOperation); @@ -3374,7 +3378,12 @@ RawDataService.addClassProperties({ unregisterDataOperationPendingReferrer: { value: function (dataOperation) { + let registration = this._pendingDataOperationById.get(dataOperation.referrerId); + if (registration) { + registration.completionPromiseResolve(); + } this._pendingDataOperationById.delete(dataOperation.referrerId); + //Backup until bug fixed //DataService.mainService.unregisterDataStreamForDataOperation(dataOperation); } From 90932aa66f39707ad858d10ae7a5d615237dd85e Mon Sep 17 00:00:00 2001 From: tejaede Date: Wed, 10 Jun 2026 17:12:21 -0500 Subject: [PATCH 2/6] Add logging / DEBUG --- core/event/event-manager.js | 19 ++++++++++-- data/service/http-service.js | 31 +++++++++++++++++++ .../mux/synchronization-data-service.js | 12 +++++-- data/service/raw-data-service.js | 9 ++++++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/core/event/event-manager.js b/core/event/event-manager.js index f9b741cd6..b2b1717eb 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -3196,6 +3196,7 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } promise = this._invokeTargetListenerEntryForEvent(iTarget, nextEntry, mutableEvent, mutableEventPhase, undefined/*currentTargetIdentifierSpecificCaptureMethodName*/, undefined/*identifierSpecificCaptureMethodName*/, undefined/*captureMethodName*/, previousPromise); + // if(previousPromise && promise) { // if(!promises) { // promises = [previousPromise, promise]; @@ -3436,7 +3437,16 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan if(promise) { var self = this; + let timeoutId = setTimeout(function () { + if (mutableEvent.target && mutableEvent.target.name) { + console.log("Unresolved Event", mutableEvent.type, mutableEvent.target.name, mutableEvent.id, mutableEvent); + } else { + console.log("Unresolved Event", mutableEvent.type, mutableEvent.id, mutableEvent); + } + + }, 2000); mutableEvent.propagationPromise = promise.then(function() { + clearTimeout(timeoutId); self._finalizeHandleEvent(mutableEvent, event); }); } else { @@ -3487,9 +3497,9 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan previousName; if (this._previousEvent) { previousName = this._previousEvent.target.name || this._previousEvent.target.objectDescriptor.name; - console.log(`[EventManager] Reset previous event ${event.identifier} ${name} ${event.type} to ${this._previousEvent.identifier} ${previousName} ${this._previousEvent.type}`); + // console.log(`[EventManager] Reset previous event ${event.identifier} ${name} ${event.type} to ${this._previousEvent.identifier} ${previousName} ${this._previousEvent.type}`); } else { - console.log(`[EventManager] Clear previous event ${event.identifier} ${name} ${event.type}`); + // console.log(`[EventManager] Clear previous event ${event.identifier} ${name} ${event.type}`); } } @@ -3664,6 +3674,11 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan this.unregisterTargetEventListener(iTarget, mutableEvent.type, listener, listenerEntry); } + if (result && result.then) { + mutableEvent.triggeredTargets = mutableEvent.triggeredTargets || []; + mutableEvent.triggeredTargets.push({target: iTarget, entry: listenerEntry, name: currentTargetIdentifierSpecificPhaseMethodName, result: result}); + } + return result; } diff --git a/data/service/http-service.js b/data/service/http-service.js index c52ce6cf6..bdc3ddfb9 100644 --- a/data/service/http-service.js +++ b/data/service/http-service.js @@ -113,6 +113,10 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService console.debug(this.name+" handleReadOperation(): EmploymentPosition read operation "+readOperation.id+" for "+readOperation.data.readExpressions+", "+readOperation.criteria.toString()); } + // if(readOperation.target.name === "Person" || ) { + console.log(this.name+" handleReadOperation(): read operation "+readOperation.id); + // } + /* This is to temporarily prevents a RawDataService to attempt to handle a readOperation that comes from a query coming from a mapping's converter that will have a very RawData-specific criteria that @@ -161,6 +165,14 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService } } + + let timeoutId = setTimeout(function () { + console.log("HttpService Unresolved promise", readOperation.id, readOperation); + }, 2000); + readOperationCompletionPromise.then(function () { + clearTimeout(timeoutId); + }) + //If we've been asked to return a promise for the read Completion Operation, we do so. Again, this is fragile. IT HAS TO MOVE UP TO RAW DATA SERVICE //WE CAN'T RELY ON INDIVIDUAL DATA SERVICE IMPLEMENTORS TO KNOW ABOUT THAT... if (this.promisesReadCompletionOperation) { @@ -198,6 +210,11 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService readOperationCompletionPromise = readOperationCompletionPromiseResolve = readOperationCompletionPromiseReject = undefined; } + let isTracking = readOperation.target.name === "Person" || readOperation.target.name === "EmploymentPositionStaffing"; + // if(readOperation.target.name === "Person") { + // console.log(this.name+" handleReadOperation(): Person read operation "+readOperation.id); + // } + if (this.authenticationPolicy && this.authenticationPolicy === AuthenticationPolicy.UP_FRONT) { let identityPromise; @@ -290,6 +307,10 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService return resolvedIdentity.objectDescriptor.propertyDescriptorNamed("accessTokens").valueDescriptor .then((resolvedAccessTokenDescriptor) => { + if (isTracking) { + console.log("HttpService Resolve AcccesTokenDescriptor", readOperation.id); + } + let accessTokenDescriptor = resolvedAccessTokenDescriptor ? resolvedAccessTokenDescriptor : this.accessTokenDescriptor; if (!registeredAccessToken && !accessTokenDescriptor) { @@ -313,6 +334,9 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService tokenDataQuery.hints = {referrerOperation: readOperation}; return tokenQueryDataStream.then((result) => { + if (isTracking) { + console.log("HttpService Resolve AccessToken", readOperation.id); + } if (result && result.length === 1) { let accessToken = result[0]; this.registerAccessTokenForIdentity(accessToken, resolvedIdentity); @@ -361,6 +385,9 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService this.mapDataOperationToRawDataOperations(readOperation, readOperations) .then(() => { + if (isTracking) { + console.log("HttpService MapToRawOperations AccessToken", readOperation.id, readOperations?.length === 0); + } if(readOperations?.length === 0) { let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, []); @@ -384,6 +411,10 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService } else { + if (isTracking) { + console.log("HttpService MapToRequests", readOperation.id, readOperations?.length === 0); + } + let iMapping = this.mappingForObjectDescriptor(iReadOperation.target); if (typeof iMapping.mapDataOperationToFetchRequests === "function") { iMapping.mapDataOperationToFetchRequests(iReadOperation, fetchRequests); diff --git a/data/service/mux/synchronization-data-service.js b/data/service/mux/synchronization-data-service.js index f79730964..637d638a8 100644 --- a/data/service/mux/synchronization-data-service.js +++ b/data/service/mux/synchronization-data-service.js @@ -123,13 +123,14 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu get _trackedTypes() { if (!this.__trackedTypes) { this.__trackedTypes = new Set([ - "JobRole" + "Person" ]); } return this.__trackedTypes; } _logTypeEvent(objectDescriptor, /*message, element1, element2, ... elementN*/) { + let stack = new Error().stack; let args = Array.from(arguments), logArgs = args.slice(1); if (typeof logArgs[0] === "string") { @@ -137,6 +138,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu } else { logArgs.unshift("[SynchronizationDataService]"); } + // logArgs.push(stack.split("\n").slice(1, 4).join("\n")); if (!this._trackedTypes || !this._trackedTypes.size) { console.log.apply(console, logArgs); } else if (this._trackedTypes.has(objectDescriptor.name)) { @@ -1190,7 +1192,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu //Now that all is done, we're saving: return promise.then( () => { - this._logTypeEvent(readCompletedOperation.referrer.target, "<<<<<<<<<<<<<<<<<<<<<<<<<<<-> Service capture ReadCompletedOperation "+readCompletedOperation.id+": saving changes from "+readCompletedOperation.rawDataService.identifier+", referrer "+readCompletedOperation.referrer.id+", for "+readCompletedOperation.referrer.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer.criteria); + this._logTypeEvent(readCompletedOperation.referrer.target, "<<<<<<<<<<<<<<<<<<<<<<<<<<<-> Service capture ReadCompletedOperation POST COMPLETED"+readCompletedOperation.id+": saving changes from "+readCompletedOperation.rawDataService.identifier+", referrer "+readCompletedOperation.referrer.id+", for "+readCompletedOperation.referrer.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer.criteria); /* one more thing: if it's a readOperation for a relationship, we need to make sure the join actually happens. @@ -1344,7 +1346,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu } - this._logTypeEvent(readCompletedOperation.referrer?.target, "Capture ReadCompletedOperation "+readCompletedOperation.id+" from "+readCompletedOperation.rawDataService.identifier+", referrer "+readCompletedOperation.referrer?.id+", for "+readCompletedOperation.referrer?.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer?.criteria+": ", readCompletedOperation.data); + this._logTypeEvent(readCompletedOperation.referrer?.target, "Capture ReadCompletedOperation BEGIN "+readCompletedOperation.id+" from "+readCompletedOperation.rawDataService.identifier+", referrer "+readCompletedOperation.referrer?.id+", for "+readCompletedOperation.referrer?.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer?.criteria+": ", readCompletedOperation.data); //Record the read completion from that service: if(readCompletedOperation.type === ReadCompletedOperationType) { @@ -1631,6 +1633,10 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu unregisterReadOperation(aReadOperation) { this._childDataServiceReadCompletionOperationByReadOperation.delete(aReadOperation); + // if (aReadOperation.rawDataService) { + + // } + // aReadOperation.hints.rawDataService.unregisterPendingDataOperation(aReadOperation); } captureSynchronizationDataServiceReadFailedOperation(readFailedOperation) { diff --git a/data/service/raw-data-service.js b/data/service/raw-data-service.js index c4d5d29a0..017340de1 100644 --- a/data/service/raw-data-service.js +++ b/data/service/raw-data-service.js @@ -3345,6 +3345,9 @@ RawDataService.addClassProperties({ dataOperationRegistration = { dataOperation: dataOperation }; + if (dataOperation.target.name === "Person") { + console.log("RawDataService.registerPendingDataOperationWithContext", this.name, dataOperation.id, dataOperation); + } if (context) { dataOperationRegistration.context = context; @@ -3367,6 +3370,9 @@ RawDataService.addClassProperties({ unregisterPendingDataOperation: { value: function (dataOperation) { let registration = this._pendingDataOperationById.get(dataOperation.id); + if (dataOperation.target.name === "Person") { + console.log("RawDataService.unregisterPendingDataOperation", dataOperation.id, !!registration, dataOperation) + } if (registration) { registration.completionPromiseResolve(); } @@ -3379,6 +3385,9 @@ RawDataService.addClassProperties({ unregisterDataOperationPendingReferrer: { value: function (dataOperation) { let registration = this._pendingDataOperationById.get(dataOperation.referrerId); + if (dataOperation.target.name === "Person") { + console.log("RawDataService.unregisterPendingDataOperationReferrer", dataOperation.id, dataOperation.referrerId, !!registration, dataOperation) + } if (registration) { registration.completionPromiseResolve(); } From e61dcadb80f1d55830b6de154b79f102071756e4 Mon Sep 17 00:00:00 2001 From: tejaede Date: Tue, 16 Jun 2026 13:57:40 -0500 Subject: [PATCH 3/6] .... --- core/event/event-manager.js | 78 +++++++++++++------ .../raw-foreign-value-to-object-converter.js | 6 ++ data/service/data-service.js | 9 +++ data/service/expression-data-mapping.js | 50 ++++++++++++ data/service/http-service.js | 15 +++- .../mux/synchronization-data-service.js | 9 ++- data/service/raw-data-service.js | 7 ++ .../serialized-data-service.js | 25 ++++++ 8 files changed, 167 insertions(+), 32 deletions(-) diff --git a/core/event/event-manager.js b/core/event/event-manager.js index b2b1717eb..b736c8ffb 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -3251,10 +3251,21 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } }, + _trackedTargets: { + value: new Set(["Person", "OAuthAccessToken", "EmploymentPositionStaffing"]) + }, + handleEvent: { enumerable: false, value: function (event) { + if (event.target.name && this._trackedTargets.has(event.target.name) && event.type.indexOf("Operation") !== -1) { + let queued = this._activeEventsByType.has(event.type) && !this._hasActiveReferrer(event); + console.log("EventManager Event", event.target.name, event.id, event.referrerId, event, { + queued: queued, + firstOfKind: !queued && !this._activeEventsByType.has(event.type) + }); + } if (this._activeEventsByType.has(event.type) && !this._hasActiveReferrer(event)) { if (!this._eventQueueByType.has(event.type)) { this._eventQueueByType.set(event.type, []); @@ -3319,19 +3330,23 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan targetEntry, targetEntryForEventType, promise; - if (event.tracksDispatchChain) { - if (this._previousEvent && this._previousEvent.dispatchChain && this._previousEvent.dispatchChain.length && event.dispatchChain) { - // console.log(`[EventManager] Mark Event ${event.target.objectDescriptor.name}`); - event.dispatchChain.push.apply(event.dispatchChain, this._previousEvent.dispatchChain); - event.dispatchChain.push(this._previousEvent); - } else if (this._previousEvent && event.dispatchChain) { - // console.log(`[EventManager] Push Previous Event ${event.target.objectDescriptor.name}`); - event.dispatchChain.push(this._previousEvent); - } else { - // console.log(`[EventManager] Record initial event ${event.target.objectDescriptor.name}`); - } - this._previousEvent = event; - } + if (event.target.name && this._trackedTargets.has(event.target.name) && event.type.indexOf("Operation") !== -1) { + console.log("EventManager HandleEvent", event.target.name, event.id, event.referrerId); + } + + // if (event.tracksDispatchChain) { + // if (this._previousEvent && this._previousEvent.dispatchChain && this._previousEvent.dispatchChain.length && event.dispatchChain) { + // // console.log(`[EventManager] Mark Event ${event.target.objectDescriptor.name}`); + // event.dispatchChain.push.apply(event.dispatchChain, this._previousEvent.dispatchChain); + // event.dispatchChain.push(this._previousEvent); + // } else if (this._previousEvent && event.dispatchChain) { + // // console.log(`[EventManager] Push Previous Event ${event.target.objectDescriptor.name}`); + // event.dispatchChain.push(this._previousEvent); + // } else { + // // console.log(`[EventManager] Record initial event ${event.target.objectDescriptor.name}`); + // } + // this._previousEvent = event; + // } if(this.isBrowser) { if( @@ -3439,7 +3454,16 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan var self = this; let timeoutId = setTimeout(function () { if (mutableEvent.target && mutableEvent.target.name) { - console.log("Unresolved Event", mutableEvent.type, mutableEvent.target.name, mutableEvent.id, mutableEvent); + if (mutableEvent.referredOperations && mutableEvent.referredOperations.length) { + let ancestry = mutableEvent.referredOperations.map(function (referred) { + return " " + referred.type + ":" + referred.target.name + ":" + referred.id + ":" + referred.rawDataService?.name; + }).join("\n"); + ancestry = "Referred: \n" + ancestry; + console.log("Unresolved Event", mutableEvent.type, mutableEvent.target.name, mutableEvent.id, ancestry, mutableEvent); + + } else { + console.log("Unresolved Event", mutableEvent.type, mutableEvent.target.name, mutableEvent.id, mutableEvent); + } } else { console.log("Unresolved Event", mutableEvent.type, mutableEvent.id, mutableEvent); } @@ -3478,6 +3502,10 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan } } + if (mutableEvent.target && mutableEvent.target.name && mutableEvent.target.name !== "Transaction") { + console.log("EventManager _finalizeHandleEvent", mutableEvent.target.name, mutableEvent.id, mutableEvent.referrerId); + } + //Handle next event let type = mutableEvent.type, next; @@ -3491,17 +3519,17 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan this._eventQueueByType.delete(type); } - if (this._previousEvent === event || this._previousEvent === mutableEvent) { - this._previousEvent = event.dispatchChain[event.dispatchChain.length - 1]; - let name = event.target.name || event.target.objectDescriptor.name, - previousName; - if (this._previousEvent) { - previousName = this._previousEvent.target.name || this._previousEvent.target.objectDescriptor.name; - // console.log(`[EventManager] Reset previous event ${event.identifier} ${name} ${event.type} to ${this._previousEvent.identifier} ${previousName} ${this._previousEvent.type}`); - } else { - // console.log(`[EventManager] Clear previous event ${event.identifier} ${name} ${event.type}`); - } - } + // if (this._previousEvent === event || this._previousEvent === mutableEvent) { + // this._previousEvent = event.dispatchChain[event.dispatchChain.length - 1]; + // let name = event.target.name || event.target.objectDescriptor.name, + // previousName; + // if (this._previousEvent) { + // previousName = this._previousEvent.target.name || this._previousEvent.target.objectDescriptor.name; + // // console.log(`[EventManager] Reset previous event ${event.identifier} ${name} ${event.type} to ${this._previousEvent.identifier} ${previousName} ${this._previousEvent.type}`); + // } else { + // // console.log(`[EventManager] Clear previous event ${event.identifier} ${name} ${event.type}`); + // } + // } } }, diff --git a/data/converter/raw-foreign-value-to-object-converter.js b/data/converter/raw-foreign-value-to-object-converter.js index 6b8e505c9..d67747a59 100644 --- a/data/converter/raw-foreign-value-to-object-converter.js +++ b/data/converter/raw-foreign-value-to-object-converter.js @@ -133,6 +133,10 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( //var localResult, localPartialResult; + if (typeToFetch.name === "EmploymentPosition" || typeToFetch.name === "EmploymentPositionStaffing" || typeToFetch.name === "Organization" ) { + console.log("ExpressionDataMapping._fetchConvertedDataForObjectDescriptorCriteria", typeToFetch, currentRule.propertyDescriptor.name, referrerOperation && referrerOperation.id, criteria); + } + /* Leaving a trace of localPartialResult here. Unless I'm missing something, the problem with a partial result is that we don't really have an easy way to return a partial result with the promise-based API, @@ -734,6 +738,8 @@ exports.RawForeignValueToObjectConverter = RawValueToObjectConverter.specialize( criteria, query; + + if(this.foreignDescriptorMappings) { /* Needs to loop on the mapping and evaluate value. If v is an array, it's possible diff --git a/data/service/data-service.js b/data/service/data-service.js index e9b224b81..43c41b39a 100644 --- a/data/service/data-service.js +++ b/data/service/data-service.js @@ -6486,6 +6486,13 @@ DataService.addClassProperties( // make sure type is an object descriptor or a data object descriptor. query.type = this.objectDescriptorForType(query.type); + // if (query.type.name === "EmploymentPosition" || query.type.name === "EmploymentPositionStaffing" || query.type.name === "Organization") { + // let referred = query.hints.referrerOperations ? query.hints.referrerOperations.map(function (operation) { + // return operation.id + // }).join(",") : query.hints.referrerOperation ? query.hints.referrerOperation.id : ""; + // console.log("DataService.fetchData", query.type.name, referred); + // } + if (this.supportsDataOperation) { //Check if we already have a DataStream pending for that same query: if ((stream = this.registeredDataStreamMapForDataQuery(query))) { @@ -6552,6 +6559,8 @@ DataService.addClassProperties( // stream.dataError(e); // } + + try { var readOperation = new DataOperation(); diff --git a/data/service/expression-data-mapping.js b/data/service/expression-data-mapping.js index 300f21b61..8ab703624 100644 --- a/data/service/expression-data-mapping.js +++ b/data/service/expression-data-mapping.js @@ -1396,6 +1396,10 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData */ service.mappingWillMapRawDataToObjectProperty(this, data, object, aRule.targetPath, context, mappingScope); + if (data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" && object.dataIdentifier.typeName === "EmploymentPositionStaffing") { + console.log("ExpressionDataMapping.mapProperty START", aRule.targetPath); + } + // console.log("mapRawDataToObject "+ this.service.dataIdentifierForObject(object)+" WILL MAP "+ aRule.targetPath); result = this.mapRawDataToObjectProperty(data, object, aRule.targetPath, context, mappingScope, registerMappedPropertiesAsChanged); @@ -1403,7 +1407,20 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData if (this._isAsync(result)) { const targetPath = aRule.targetPath, propertyDescriptor = aRule.propertyDescriptor; + if ((data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPositionStaffing") + || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition")) { + // console.log("ExpressionDataMapping.mapProperty START", targetPath); + window.unmappedProperties = window.unmappedProperties || new Set(); + window.unmappedProperties.add(object.dataIdentifier.typeName + "." + targetPath); + } + result = result.then((resultValue) => { + if ((data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPositionStaffing") + || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition")) { + // console.log("ExpressionDataMapping.mapProperty DONE", targetPath); + window.unmappedProperties.delete(object.dataIdentifier.typeName + "." + targetPath); + } + // console.log("ExpressionDataMapping.mapProperty DONE", targetPath); this._registerMappedPropertyValueAsChangesForCreatedObject(targetPath, resultValue, (changesForDataObject || (changesForDataObject = service.changesForDataObject(object))), object, (mainService || (mainService = service.mainService))); /* Tell our service: mappingDidMapRawDataToObjectPropertyValue @@ -1414,6 +1431,9 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData return resultValue; }); } else { + if (data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" && object.dataIdentifier.typeName === "EmploymentPositionStaffing") { + console.log("ExpressionDataMapping.mapProperty DONE", aRule.targetPath); + } this._registerMappedPropertyValueAsChangesForCreatedObject(aRule.targetPath, result, (changesForDataObject || (changesForDataObject = service.changesForDataObject(object))), object, (mainService || (mainService = service.mainService))); /* Tell our service: mappingDidMapRawDataToObjectPropertyValue @@ -1657,6 +1677,32 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData * */ mapRawDataToObjectProperty: { + value: function (data, object, propertyName, context, scope, registerMappedPropertiesAsChanged) { + if (object.objectDescriptor.name === "Person" && (propertyName === "employmentPosition" || propertyName === "employmentHistory")) { + console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); + } + // if (object.dataIdentifier.typeName === "EmploymentPositionStaffing") { + // console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); + // } + if (object.dataIdentifier.typeName === "EmploymentPosition") { + console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); + } + if (object.objectDescriptor.name === "Person" || object.dataIdentifier.typeName === "EmploymentPositionStaffing" || object.dataIdentifier.typeName === "EmploymentPosition") { + let timeoutid = setTimeout(function () { + console.log("ExpressionDataMapping: Failed to map " + propertyName + " on " + object.objectDescriptor.name, data, context, scope); + }, 4000); + let result = this.___mapRawDataToObjectProperty(data, object, propertyName, context, scope, registerMappedPropertiesAsChanged); + result.then(function () { + clearTimeout(timeoutid); + }); + return result; + } else { + return this.___mapRawDataToObjectProperty(data, object, propertyName, context, scope, registerMappedPropertiesAsChanged); + } + } + }, + + ___mapRawDataToObjectProperty: { value: function (data, object, propertyName, context, scope = this._scope.nest(data), registerMappedPropertiesAsChanged) { var rule = this.objectMappingRuleForPropertyName(propertyName), propertyDescriptor = rule && this.objectDescriptor.propertyDescriptorForName(propertyName); @@ -1670,6 +1716,10 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData locales, debug = DataService.debugProperties.has(propertyName) || (rule && rule.debug === true); + if (object.objectDescriptor.name === "Person" && (propertyName === "employmentPosition" || propertyName === "employmentHistory")) { + console.log("ExpressionDataMapping 2: " + object.objectDescriptor.name + " " + propertyName, context, data); + } + //Simplistic and potentially wrong, but if there's no properties on data for that rule, then there's no point doing it // if(rule && !data.hasOwnProperty(rule.sourcePath)) { diff --git a/data/service/http-service.js b/data/service/http-service.js index bdc3ddfb9..d69d753f1 100644 --- a/data/service/http-service.js +++ b/data/service/http-service.js @@ -167,7 +167,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService let timeoutId = setTimeout(function () { - console.log("HttpService Unresolved promise", readOperation.id, readOperation); + console.log("HttpService Unresolved promise", readOperation.target.name, readOperation.id, readOperation); }, 2000); readOperationCompletionPromise.then(function () { clearTimeout(timeoutId); @@ -308,7 +308,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService .then((resolvedAccessTokenDescriptor) => { if (isTracking) { - console.log("HttpService Resolve AcccesTokenDescriptor", readOperation.id); + console.log("HttpService Resolve AccessTokenDescriptor", readOperation.id); } let accessTokenDescriptor = resolvedAccessTokenDescriptor ? resolvedAccessTokenDescriptor : this.accessTokenDescriptor; @@ -319,6 +319,10 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService } else { + if (isTracking) { + console.log("HttpService Request AccessToken", readOperation.id); + } + /* In the case where the identity is cached locally, and the access token is too. @@ -356,6 +360,9 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService }) .catch(error => { + if (isTracking) { + console.log("HttpService Failed AccessToken", readOperation.id); + } let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); console.error("Identity promise failed with error", error); return responseOperation; @@ -461,7 +468,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService // } let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, rawData); - console.log("\t" + this.identifier + " handleReadOperation dispatch A responseOperation " + responseOperation.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); + console.log("\t" + this.identifier + " handleReadOperation dispatch A responseOperation " + responseOperation.id, responseOperation.referrer.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); @@ -480,7 +487,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService // responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); //Send an empty response instead let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, []); - console.log("\t" + this.identifier + " handleReadOperation dispatch B responseOperation " + responseOperation.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); + console.log("\t" + this.identifier + " handleReadOperation dispatch B responseOperation " + responseOperation.id, responseOperation.referrer.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); diff --git a/data/service/mux/synchronization-data-service.js b/data/service/mux/synchronization-data-service.js index 637d638a8..9ff8617fd 100644 --- a/data/service/mux/synchronization-data-service.js +++ b/data/service/mux/synchronization-data-service.js @@ -123,7 +123,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu get _trackedTypes() { if (!this.__trackedTypes) { this.__trackedTypes = new Set([ - "Person" + "Person", "EmploymentPosition", "EmploymentPositionStaffing", "Organization", "IncorporatedOrganization" ]); } return this.__trackedTypes; @@ -753,6 +753,9 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu // mappedObjects.push(dataObject); + // if (objectDescriptor.name === "Person" && rawData.id === "8b286280-6944-432f-8940-39be0117b14f") { + // debugger; + // } /* We're syncing, so we need to grab as much data as we can if we have no guidelines @@ -1143,7 +1146,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu // iObject.originDataSnapshot = rawData[i]; if( rawData[i]) { - this._logTypeEvent(readCompletedOperation.referrer.target, "<<<<<<<<<<<<<<<<<<<<<<<<<<<-> Service capture ReadCompletedOperation "+readCompletedOperation.id+": _syncObjectDescriptorRawDataFromReadCompletedOperation from "+readCompletedOperation.rawDataService.identifier+", referrer "+readCompletedOperation.referrer.id+", for "+readCompletedOperation.referrer.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer.criteria); + this._logTypeEvent(readCompletedOperation.referrer.target, "<<<<<<<<<<<<<<<<<<<<<<<<<<<-> Service capture ReadCompletedOperation "+readCompletedOperation.id+": _syncObjectDescriptorRawDataFromReadCompletedOperation from "+readCompletedOperation.rawDataService.identifier+" Iterate Raw Data "+i+", referrer "+readCompletedOperation.referrer.id+", for "+readCompletedOperation.referrer.target.name + (readCompletedOperation.referrer?.data?.readExpressions? (" "+readCompletedOperation.referrer?.data?.readExpressions) : "") + " like "+ readCompletedOperation.referrer.criteria); //TODO Test if rawData[i] is already a mapped object and, if so, set iMappingResult to Promise.resolve(rawData[i]) // WARNING: We might need to add logic inside _syncObjectDescriptorRawDataFromReadCompletedOperation @@ -1659,7 +1662,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu this.registerChildDataServiceReadCompletionOperation(readFailedOperation); - this._logTypeEvent(readFailedOperation.referrer.target, "Sync Service capture ReadFailedOperation "+readFailedOperation.id+" from "+readFailedOperation.rawDataService.identifier+", referrer "+readFailedOperation.referrer.id+", for "+readFailedOperation.referrer.target.name + (readFailedOperation.referrer?.data?.readExpressions? (" "+readFailedOperation.referrer?.data?.readExpressions) : "") + " like "+ readFailedOperation.referrer.criteria+": ", readFailedOperation.data); + // this._logTypeEvent(readFailedOperation.referrer.target, "Sync Service capture ReadFailedOperation "+readFailedOperation.id+" from "+readFailedOperation.rawDataService.identifier+", referrer "+readFailedOperation.referrer.id+", for "+readFailedOperation.referrer.target.name + (readFailedOperation.referrer?.data?.readExpressions? (" "+readFailedOperation.referrer?.data?.readExpressions) : "") + " like "+ readFailedOperation.referrer.criteria+": ", readFailedOperation.data); if((readFailedOperation.data.name === DataOperationErrorNames.DatabaseMissing) || (readFailedOperation.data.name === DataOperationErrorNames.ObjectDescriptorStoreMissing) ) { diff --git a/data/service/raw-data-service.js b/data/service/raw-data-service.js index 017340de1..da1a586f5 100644 --- a/data/service/raw-data-service.js +++ b/data/service/raw-data-service.js @@ -1535,6 +1535,10 @@ RawDataService.addClassProperties({ return Promise.resolveNull; } + if (type.name === "EmploymentPositionStaffing") { + console.log("RawDataService.resolveObjectForTypeRawData", type.name, rawData, context); + } + //Retrieves an existing object is responsible data service is uniquing, or creates one object = this.getDataObject(type, rawData, dataIdentifier, context); @@ -1555,6 +1559,9 @@ RawDataService.addClassProperties({ if (Promise.is(result)) { return result.then(function () { + if (type.name === "EmploymentPositionStaffing") { + console.log("RawDataService.resolveObjectForTypeRawData DONE", type.name, rawData, context); + } return object; }); } else { diff --git a/data/service/serialized-data-service.mod/serialized-data-service.js b/data/service/serialized-data-service.mod/serialized-data-service.js index 33b84d0db..ba68e0916 100644 --- a/data/service/serialized-data-service.mod/serialized-data-service.js +++ b/data/service/serialized-data-service.mod/serialized-data-service.js @@ -392,6 +392,12 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi __mapRawDataPropertyToObject (record, property, valueDescriptor, object, mainService) { let objectDescriptor = object.objectDescriptor, iPropertyDescriptor = objectDescriptor.propertyDescriptorNamed(property); + + if (object.objectDescriptor.name === "IncorporatedOrganization") { + window.incOrgProperties = window.incOrgProperties || new Set(); + // debugger + window.incOrgProperties.add(property); + } if(iPropertyDescriptor.cardinality === 1) { let iPropertyValue = object[property]; if(typeof iPropertyValue === "string" /* would sure be handy to actually have a uuid tye right now...*/) { @@ -399,10 +405,17 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi return this._objectPromiseForDataIdentifier(aDataIdentifier, mainService) .then((iObjectValue) => { + if (object.objectDescriptor.name === "IncorporatedOrganization") { + window.incOrgProperties.delete(property); + } + object[property] = iObjectValue }) } else { + if (object.objectDescriptor.name === "IncorporatedOrganization") { + window.incOrgProperties.delete(property); + } object[property] = record[property]; } } else { @@ -431,6 +444,9 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi ); } return Promise.all(mappingPromises).then((values) => { + if (object.objectDescriptor.name === "IncorporatedOrganization") { + window.incOrgProperties.delete(property); + } object[property].splice.apply(object[property], [0, Infinity].concat(values.filter((value) => !!value))); return; }); @@ -439,6 +455,9 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi throw "mapObjectToRawData for a property that is Map needs to be implemented"; } } else { + if (object.objectDescriptor.name === "IncorporatedOrganization") { + window.incOrgProperties.delete(property); + } object[property] = iPropertyValues; } } @@ -452,6 +471,8 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi mappingPromises = []; + + for(let countI = recordKeys.length, i = 0; (i Date: Wed, 17 Jun 2026 17:04:45 -0500 Subject: [PATCH 4/6] ... --- core/event/event-manager.js | 41 ++++++++----- data/service/data-operation.js | 25 +++++++- data/service/data-service.js | 4 ++ data/service/expression-data-mapping.js | 6 +- data/service/http-service.js | 16 ++--- .../mux/synchronization-data-service.js | 2 +- data/service/raw-data-service.js | 18 ++++-- .../serialized-data-service.js | 58 +++++++++++-------- .../web-socket-data-operation-service.js | 1 + worker/data-worker.js | 6 +- 10 files changed, 120 insertions(+), 57 deletions(-) diff --git a/core/event/event-manager.js b/core/event/event-manager.js index b736c8ffb..e55e15e8f 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -3259,6 +3259,15 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan enumerable: false, value: function (event) { + if (typeof window === "object" && !window._eventQueueByType) { + window.eventQueueByType = this._eventQueueByType; + window.activeEventsByType = this._activeEventsByType; + } + if (typeof window === "undefined") { + this._handleEvent(event); + return; + } + if (event.target.name && this._trackedTargets.has(event.target.name) && event.type.indexOf("Operation") !== -1) { let queued = this._activeEventsByType.has(event.type) && !this._hasActiveReferrer(event); console.log("EventManager Event", event.target.name, event.id, event.referrerId, event, { @@ -3500,25 +3509,27 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan document.body.removeEventListener("DOMAttrModified", this.domModificationEventHandler, true); document.body.removeEventListener("DOMCharacterDataModified", this.domModificationEventHandler, true); } - } - if (mutableEvent.target && mutableEvent.target.name && mutableEvent.target.name !== "Transaction") { - console.log("EventManager _finalizeHandleEvent", mutableEvent.target.name, mutableEvent.id, mutableEvent.referrerId); - } + // if (mutableEvent.target && mutableEvent.target.name && mutableEvent.type.indexOf("Operation") !== -1) { + // console.log("EventManager _finalizeHandleEvent", mutableEvent.type, mutableEvent.target.name, mutableEvent.id, mutableEvent.referrerId, mutableEvent); + // } - //Handle next event - let type = mutableEvent.type, - next; - if (this._eventQueueByType.has(type) && this._eventQueueByType.get(type).length) { - next = this._eventQueueByType.get(type).pop(); - this._activeEventsByType.get(type).delete(event); - this._activeEventsByType.get(type).add(next); - this._handleEvent(next); - } else { - this._activeEventsByType.delete(type); - this._eventQueueByType.delete(type); + //Handle next event + let type = mutableEvent.type, + next; + if (this._eventQueueByType.has(type) && this._eventQueueByType.get(type).length) { + next = this._eventQueueByType.get(type).pop(); + this._activeEventsByType.get(type).delete(event); + this._activeEventsByType.get(type).add(next); + this._handleEvent(next); + } else { + this._activeEventsByType.delete(type); + this._eventQueueByType.delete(type); + } } + + // if (this._previousEvent === event || this._previousEvent === mutableEvent) { // this._previousEvent = event.dispatchChain[event.dispatchChain.length - 1]; // let name = event.target.name || event.target.objectDescriptor.name, diff --git a/data/service/data-operation.js b/data/service/data-operation.js index 923bc7bb7..acb6eced5 100644 --- a/data/service/data-operation.js +++ b/data/service/data-operation.js @@ -270,6 +270,10 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM serializer.setProperty("timeStamp", this.timeStamp); serializer.setProperty("clientId", this.clientId); + if (this.type === "readCompletedOperation" && this.target && this.target.name === "Organization") { + debugger; + } + if(this.target) { serializer.setProperty("target", this.target); @@ -297,10 +301,14 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM serializer.setProperty("referrerId", this.referrerId); } - if(this.referrer) { + if (this.referrer) { serializer.setProperty("referrer", this.referrer); } + if (this.referrers) { + serializer.setProperty("referrers", this.referrers); + } + serializer.setProperty("criteria", this._criteria); /* @@ -420,6 +428,10 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM this.referrer = value; } + value = deserializer.getProperty("referrers"); + if (value !== void 0) { + this.referrers = value; + } value = deserializer.getProperty("criteria"); if (value !== void 0) { @@ -695,13 +707,22 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM return this._referrer; }, set: function(value) { + if (Array.isArray(value)) { + debugger; + } if(value !== this._referrer) { if (this._referrer) { this._referrer.referredOperations.delete(this); } this._referrer = value; if (this._referrer) { - this._referrer.referredOperations.push(this); + if (this._referrer.referredOperations) { + this._referrer.referredOperations.push(this); + } else { + debugger; + this._referrer.referredOperations = [this]; + } + } } } diff --git a/data/service/data-service.js b/data/service/data-service.js index 43c41b39a..cd7b3fbb1 100644 --- a/data/service/data-service.js +++ b/data/service/data-service.js @@ -6598,7 +6598,11 @@ DataService.addClassProperties( if (query.criteria) { //readOperation.criteria = criteria.clone(); readOperation.criteria = query.criteria; + if (query.criteria.parameters === "019a4e83-203a-76de-bf6f-7f26739d65fd") { + window.suborgOperation = readOperation; + } } + if (query.sizeLimit) { readOperation.data.sizeLimit = query.sizeLimit; } diff --git a/data/service/expression-data-mapping.js b/data/service/expression-data-mapping.js index 8ab703624..40dfa50b1 100644 --- a/data/service/expression-data-mapping.js +++ b/data/service/expression-data-mapping.js @@ -1408,7 +1408,8 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData const targetPath = aRule.targetPath, propertyDescriptor = aRule.propertyDescriptor; if ((data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPositionStaffing") - || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition")) { + || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition") || + (object.dataIdentifier.typeName === "JobRole")) { // console.log("ExpressionDataMapping.mapProperty START", targetPath); window.unmappedProperties = window.unmappedProperties || new Set(); window.unmappedProperties.add(object.dataIdentifier.typeName + "." + targetPath); @@ -1416,7 +1417,8 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData result = result.then((resultValue) => { if ((data.employeeId === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPositionStaffing") - || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition")) { + || (data.id === "8b286280-6944-432f-8940-39be0117b14f" || object.dataIdentifier.typeName === "EmploymentPosition") || + (object.dataIdentifier.typeName === "JobRole")) { // console.log("ExpressionDataMapping.mapProperty DONE", targetPath); window.unmappedProperties.delete(object.dataIdentifier.typeName + "." + targetPath); } diff --git a/data/service/http-service.js b/data/service/http-service.js index d69d753f1..87bd165db 100644 --- a/data/service/http-service.js +++ b/data/service/http-service.js @@ -363,7 +363,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService if (isTracking) { console.log("HttpService Failed AccessToken", readOperation.id); } - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), error, null); console.error("Identity promise failed with error", error); return responseOperation; }); @@ -396,7 +396,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService console.log("HttpService MapToRawOperations AccessToken", readOperation.id, readOperations?.length === 0); } if(readOperations?.length === 0) { - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, []); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), null, []); responseOperation.target.dispatchEvent(responseOperation); @@ -467,7 +467,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService // rawDataObject[iReadExpression] = iPropertyDescriptor.defaultValue || iPropertyDescriptor.defaultFalsyValue; // } - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, rawData); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), null, rawData); console.log("\t" + this.identifier + " handleReadOperation dispatch A responseOperation " + responseOperation.id, responseOperation.referrer.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); @@ -484,9 +484,9 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService if (readOperation.clientId) { error.stack = null; } - // responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); + // responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), error, null); //Send an empty response instead - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, []); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), null, []); console.log("\t" + this.identifier + " handleReadOperation dispatch B responseOperation " + responseOperation.id, responseOperation.referrer.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); @@ -533,7 +533,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService }) .catch((error) => { - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), error, null); console.error(error); console.log("\t" + this.identifier + " handleReadOperation ERROR dispatch D responseOperation " + responseOperation.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); @@ -810,7 +810,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService mapping.mapFetchResponseToRawData(responseContent, rawData); //console.debug("rawData: ",rawData); - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, null, rawData, false /*isNotLast*/, readOperation.target/*responseOperationTarget*/); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), null, rawData, false /*isNotLast*/, readOperation.target/*responseOperationTarget*/); console.log("\t" + this.identifier + " handleReadOperation dispatch " + responseOperation.type + " id " + responseOperation.id + " for read referrer id " + responseOperation.referrer.id + " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); responseOperation.target.dispatchEvent(responseOperation); @@ -824,7 +824,7 @@ var HttpService = exports.HttpService = class HttpService extends RawDataService }) .catch((error) => { console.log(this.name + " Fetch Request:", iRequest + ", error: ", error); - let responseOperation = this.responseOperationForReadOperation(readOperation.referrer ? readOperation.referrer : readOperation, error, null); + let responseOperation = this.responseOperationForReadOperation(this.relevantOperationForResponse(readOperation), error, null); console.error(error); console.log(this.identifier + " handleReadOperation dispatch ERROR responseOperation " + responseOperation.id, " for " + responseOperation.referrer.target.name + " like " + responseOperation.referrer.criteria); diff --git a/data/service/mux/synchronization-data-service.js b/data/service/mux/synchronization-data-service.js index 9ff8617fd..6b0e25648 100644 --- a/data/service/mux/synchronization-data-service.js +++ b/data/service/mux/synchronization-data-service.js @@ -123,7 +123,7 @@ exports.SynchronizationDataService = class SynchronizationDataService extends Mu get _trackedTypes() { if (!this.__trackedTypes) { this.__trackedTypes = new Set([ - "Person", "EmploymentPosition", "EmploymentPositionStaffing", "Organization", "IncorporatedOrganization" + "Person", "EmploymentPosition", "EmploymentPositionStaffing", "Organization", "IncorporatedOrganization", "JobRole" ]); } return this.__trackedTypes; diff --git a/data/service/raw-data-service.js b/data/service/raw-data-service.js index da1a586f5..1c35b7564 100644 --- a/data/service/raw-data-service.js +++ b/data/service/raw-data-service.js @@ -3392,9 +3392,9 @@ RawDataService.addClassProperties({ unregisterDataOperationPendingReferrer: { value: function (dataOperation) { let registration = this._pendingDataOperationById.get(dataOperation.referrerId); - if (dataOperation.target.name === "Person") { - console.log("RawDataService.unregisterPendingDataOperationReferrer", dataOperation.id, dataOperation.referrerId, !!registration, dataOperation) - } + // if (dataOperation.target.name === "Person") { + // console.log("RawDataService.unregisterPendingDataOperationReferrer", dataOperation.id, dataOperation.referrerId, !!registration, dataOperation) + // } if (registration) { registration.completionPromiseResolve(); } @@ -3795,16 +3795,26 @@ RawDataService.addClassProperties({ this.rawDataDone(stream); //this._thenableByOperationId.delete(operation.referrerId); this.unregisterDataOperationPendingReferrer(operation); - } + } // else { // console.log("receiving operation of type:"+operation.type+", but can't find a matching stream"); // } //console.log("handleReadCompleted -clear _thenableByOperationId- referrerId: ",operation.referrerId); + } else { + } } }, + relevantOperationForResponse: { + value: function (readOperation) { + let referrer = readOperation.referrer; + // return referrer && referrer.type !== "readCompletedOperation" ? referrer : readOperation; + return referrer && referrer.type !== "readCompletedOperation" ? referrer : readOperation; + } + }, + handleReadFailedOperation: { value: function (operation) { var stream = this.referrerContextForDataOperation(operation); diff --git a/data/service/serialized-data-service.mod/serialized-data-service.js b/data/service/serialized-data-service.mod/serialized-data-service.js index ba68e0916..b885080ff 100644 --- a/data/service/serialized-data-service.mod/serialized-data-service.js +++ b/data/service/serialized-data-service.mod/serialized-data-service.js @@ -333,7 +333,7 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi } - _objectPromiseForDataIdentifier(aDataIdentifier, mainService) { + _objectPromiseForDataIdentifier(aDataIdentifier, mainService, dataOperation) { let iObjectValue = mainService.objectForDataIdentifier(aDataIdentifier); if(!iObjectValue) { @@ -341,6 +341,12 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi let criteria = new Criteria().initWithExpression("identifier == $", aDataIdentifier.primaryKey), iObjectValueQuery = DataQuery.withTypeAndCriteria(aDataIdentifier.objectDescriptor, criteria); + console.log("SerializedDataService._objectPromiseForDataIdentifier", aDataIdentifier.typeName, aDataIdentifier.primaryKey); + + if (dataOperation) { + iObjectValueQuery.hints = {referrerOperation: dataOperation}; + } + return mainService.fetchData(iObjectValueQuery).catch((e) => { //FIXME: This should not be necessary. SynchronizationDataService should be able to @@ -363,7 +369,7 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi } /* adds a promise resolving to the value to mappingPromises passed in*/ - _mapRawDataPropertyToObject (record, property, object, mappingPromises, mainService) { + _mapRawDataPropertyToObject (record, property, object, mappingPromises, mainService, context) { let objectDescriptor = object.objectDescriptor, iPropertyDescriptor = objectDescriptor.propertyDescriptorNamed(property); @@ -376,10 +382,10 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi if(iPropertyDescriptor.valueDescriptor) { if (this._isAsync(iPropertyDescriptor.valueDescriptor)) { mappingPromises.push(iPropertyDescriptor.valueDescriptor.then((valueDescriptor) => { - return this.__mapRawDataPropertyToObject(record, property, valueDescriptor, object, mainService); + return this.__mapRawDataPropertyToObject(record, property, valueDescriptor, object, mainService, context); })); } else { - return this.__mapRawDataPropertyToObject(record, property, iPropertyDescriptor.valueDescriptor, object, mainService); + return this.__mapRawDataPropertyToObject(record, property, iPropertyDescriptor.valueDescriptor, object, mainService, context); } } else { @@ -389,32 +395,38 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi } } - __mapRawDataPropertyToObject (record, property, valueDescriptor, object, mainService) { + __mapRawDataPropertyToObject (record, property, valueDescriptor, object, mainService, context) { let objectDescriptor = object.objectDescriptor, - iPropertyDescriptor = objectDescriptor.propertyDescriptorNamed(property); + iPropertyDescriptor = objectDescriptor.propertyDescriptorNamed(property), + dataOperation = context instanceof DataOperation ? context : null; - if (object.objectDescriptor.name === "IncorporatedOrganization") { - window.incOrgProperties = window.incOrgProperties || new Set(); + let trackMapping = object.objectDescriptor.name === "IncorporatedOrganization" || object.objectDescriptor.name === "Organization" || object.objectDescriptor.name === "JobRole"; + + if (trackMapping) { + window.incOrgProperties = window.incOrgProperties || new Map(); // debugger - window.incOrgProperties.add(property); + if (!window.incOrgProperties.has(object)) { + window.incOrgProperties.set(object, new Set()); + } + window.incOrgProperties.get(object).add(property); } if(iPropertyDescriptor.cardinality === 1) { let iPropertyValue = object[property]; if(typeof iPropertyValue === "string" /* would sure be handy to actually have a uuid tye right now...*/) { let aDataIdentifier = this.dataIdentifierForTypePrimaryKey(iPropertyDescriptor.valueDescriptor, record.identifier); - return this._objectPromiseForDataIdentifier(aDataIdentifier, mainService) + return this._objectPromiseForDataIdentifier(aDataIdentifier, mainService, dataOperation) .then((iObjectValue) => { - if (object.objectDescriptor.name === "IncorporatedOrganization") { - window.incOrgProperties.delete(property); + if (trackMapping) { + window.incOrgProperties.get(object).delete(property); } object[property] = iObjectValue }) } else { - if (object.objectDescriptor.name === "IncorporatedOrganization") { - window.incOrgProperties.delete(property); + if (trackMapping) { + window.incOrgProperties.get(object).delete(property); } object[property] = record[property]; } @@ -440,12 +452,12 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi let aDataIdentifier = this.dataIdentifierForTypePrimaryKey(objectDescriptor, iPropertyValues[i]); mappingPromises.push( - this._objectPromiseForDataIdentifier(aDataIdentifier, mainService) + this._objectPromiseForDataIdentifier(aDataIdentifier, mainService, dataOperation) ); } return Promise.all(mappingPromises).then((values) => { - if (object.objectDescriptor.name === "IncorporatedOrganization") { - window.incOrgProperties.delete(property); + if (trackMapping) { + window.incOrgProperties.get(object).delete(property); } object[property].splice.apply(object[property], [0, Infinity].concat(values.filter((value) => !!value))); return; @@ -455,9 +467,9 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi throw "mapObjectToRawData for a property that is Map needs to be implemented"; } } else { - if (object.objectDescriptor.name === "IncorporatedOrganization") { - window.incOrgProperties.delete(property); - } + if (trackMapping) { + window.incOrgProperties.get(object).delete(property); + } object[property] = iPropertyValues; } } @@ -474,7 +486,7 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi for(let countI = recordKeys.length, i = 0; (i { var serializedOperation = this._serializer.serializeObject(operation); + var operationDataKBSize = sizeof(serializedOperation) / 1024; //console.debug("----> send "+operationDataKBSize+" KB operation "+serializedOperation); diff --git a/worker/data-worker.js b/worker/data-worker.js index fb5286d56..b77fc64e0 100644 --- a/worker/data-worker.js +++ b/worker/data-worker.js @@ -606,10 +606,12 @@ exports.DataWorker = Worker.specialize( /** @lends DataWorker.prototype */{ try { var deserializedOperationPromise = this.deserializer.deserializeObject(); } catch (ex) { + console.error(ex); deserializedOperationPromise = this.tryToConvertMessageToDataOperation(message); } deserializedOperationPromise.catch((error) => { + console.error(error); return this.tryToConvertMessageToDataOperation(message); }) .then((deserializedOperation) => { @@ -643,8 +645,8 @@ exports.DataWorker = Worker.specialize( /** @lends DataWorker.prototype */{ }) } } else { - console.error("No deserialization for ",serializedOperation); - return Promise.reject("Unknown message: ",serializedOperation); + console.error("No deserialization for ",message); + return Promise.reject("Unknown message: ",message); } }); From d13318f87070c2b55f381deab90e0091f5189583 Mon Sep 17 00:00:00 2001 From: tejaede Date: Tue, 23 Jun 2026 17:02:05 -0500 Subject: [PATCH 5/6] Remove logging --- data/service/expression-data-mapping.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/data/service/expression-data-mapping.js b/data/service/expression-data-mapping.js index 40dfa50b1..3323fd8ee 100644 --- a/data/service/expression-data-mapping.js +++ b/data/service/expression-data-mapping.js @@ -1680,15 +1680,7 @@ exports.ExpressionDataMapping = DataMapping.specialize(/** @lends ExpressionData */ mapRawDataToObjectProperty: { value: function (data, object, propertyName, context, scope, registerMappedPropertiesAsChanged) { - if (object.objectDescriptor.name === "Person" && (propertyName === "employmentPosition" || propertyName === "employmentHistory")) { - console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); - } - // if (object.dataIdentifier.typeName === "EmploymentPositionStaffing") { - // console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); - // } - if (object.dataIdentifier.typeName === "EmploymentPosition") { - console.log("ExpressionDataMapping: " + object.objectDescriptor.name + " " + propertyName, context); - } + if (object.objectDescriptor.name === "Person" || object.dataIdentifier.typeName === "EmploymentPositionStaffing" || object.dataIdentifier.typeName === "EmploymentPosition") { let timeoutid = setTimeout(function () { console.log("ExpressionDataMapping: Failed to map " + propertyName + " on " + object.objectDescriptor.name, data, context, scope); From 861a98f81eda35ed2b91c2c1e95133b337eac7c1 Mon Sep 17 00:00:00 2001 From: tejaede Date: Tue, 23 Jun 2026 17:02:20 -0500 Subject: [PATCH 6/6] ... --- core/event/event-manager.js | 6 +++--- data/service/data-operation.js | 3 --- data/service/raw-data-service.js | 6 ++++-- .../serialized-data-service.mod/serialized-data-service.js | 1 - 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/core/event/event-manager.js b/core/event/event-manager.js index e55e15e8f..20f52d15c 100644 --- a/core/event/event-manager.js +++ b/core/event/event-manager.js @@ -3252,7 +3252,7 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan }, _trackedTargets: { - value: new Set(["Person", "OAuthAccessToken", "EmploymentPositionStaffing"]) + value: new Set(["Person", "EmploymentPositionStaffing", "EmploymentPosition", "JobRole"]) }, handleEvent: { @@ -3294,11 +3294,11 @@ var EventManager = exports.EventManager = Montage.specialize(/** @lends EventMan value: function (event) { let referrer; if (event.referrer) { - return this._isActive(event.referrer); + return this._isActive(event.referrer) || this._hasActiveReferrer(event.referrer); } else if (event.referrers) { let i, n, isActive; for (i = 0, n = event.referrers.length; i < n && !isActive; ++i) { - isActive = this._isActive(event.referrers[i]); + isActive = this._isActive(event.referrers[i]) || this._hasActiveReferrer(event.referrers[i]); } return isActive; } diff --git a/data/service/data-operation.js b/data/service/data-operation.js index acb6eced5..502201a8c 100644 --- a/data/service/data-operation.js +++ b/data/service/data-operation.js @@ -270,9 +270,6 @@ exports.DataOperationErrorNames = DataOperationErrorNames = new Enum().initWithM serializer.setProperty("timeStamp", this.timeStamp); serializer.setProperty("clientId", this.clientId); - if (this.type === "readCompletedOperation" && this.target && this.target.name === "Organization") { - debugger; - } if(this.target) { serializer.setProperty("target", this.target); diff --git a/data/service/raw-data-service.js b/data/service/raw-data-service.js index 1c35b7564..dfd86efc0 100644 --- a/data/service/raw-data-service.js +++ b/data/service/raw-data-service.js @@ -3795,7 +3795,9 @@ RawDataService.addClassProperties({ this.rawDataDone(stream); //this._thenableByOperationId.delete(operation.referrerId); this.unregisterDataOperationPendingReferrer(operation); - } + } else { + this.unregisterDataOperationPendingReferrer(operation); + } // else { // console.log("receiving operation of type:"+operation.type+", but can't find a matching stream"); // } @@ -3811,7 +3813,7 @@ RawDataService.addClassProperties({ value: function (readOperation) { let referrer = readOperation.referrer; // return referrer && referrer.type !== "readCompletedOperation" ? referrer : readOperation; - return referrer && referrer.type !== "readCompletedOperation" ? referrer : readOperation; + return referrer && (referrer.type !== DataOperation.Type.ReadCompletedOperation && referrer.type !== DataOperation.Type.ReadFailedOperation) ? referrer : readOperation; } }, diff --git a/data/service/serialized-data-service.mod/serialized-data-service.js b/data/service/serialized-data-service.mod/serialized-data-service.js index b885080ff..977a2b4f8 100644 --- a/data/service/serialized-data-service.mod/serialized-data-service.js +++ b/data/service/serialized-data-service.mod/serialized-data-service.js @@ -341,7 +341,6 @@ exports.SerializedDataService = class SerializedDataService extends RawDataServi let criteria = new Criteria().initWithExpression("identifier == $", aDataIdentifier.primaryKey), iObjectValueQuery = DataQuery.withTypeAndCriteria(aDataIdentifier.objectDescriptor, criteria); - console.log("SerializedDataService._objectPromiseForDataIdentifier", aDataIdentifier.typeName, aDataIdentifier.primaryKey); if (dataOperation) { iObjectValueQuery.hints = {referrerOperation: dataOperation};