Skip to content

Commit 3225468

Browse files
authored
Merge pull request #51 from Timer2Ticket/20273-better-logging-context
20273 better logging context
2 parents c6d3df4 + 42f5a94 commit 3225468

File tree

10 files changed

+384
-379
lines changed

10 files changed

+384
-379
lines changed

src/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ cron.schedule('*/10 * * * * *', () => {
5656
// console.log(' -> Repeating job');
5757
job.start().then(resRepeated => {
5858
if (resRepeated) {
59-
// console.log(' -> Job repeated and now successfully done.');
59+
//console.log(' -> Job repeated and now successfully done.');
6060
return;
6161
}
6262

src/jobs/config_sync_job.ts

Lines changed: 10 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ export class ConfigSyncJob extends SyncJob {
3636
//if we get boolean, a problem occurred while getting data from service (most likely 401 or 403 error)
3737
//we dont have all the service objects and stop the job
3838
if (typeof objectsToSync === "boolean") {
39-
let message: string = 'Problem occurred while getting primary service objects.';
40-
this._jobLog.errors.push(this._errorService.createConfigJobError(message));
39+
await this.updateJobLog(primarySyncedService.errors)
4140
return false;
4241
}
4342

@@ -51,8 +50,7 @@ export class ConfigSyncJob extends SyncJob {
5150
const allServiceObjects = await syncedService.getAllServiceObjects(configLastSyncAt);
5251
//same as above, there was a problem communication problem with service. We stop the job.
5352
if (typeof allServiceObjects === "boolean") {
54-
let message: string = 'Problem occurred while getting secondary service objects';
55-
this._jobLog.errors.push(this._errorService.createConfigJobError(message));
53+
await this.updateJobLog(syncedService.errors)
5654
return false;
5755
}
5856

@@ -103,11 +101,6 @@ export class ConfigSyncJob extends SyncJob {
103101
}
104102
} catch (ex) {
105103
operationsOk = false;
106-
//TODO figure out better way to work with extra context.
107-
//temporary console log to test if this is the correct place.
108-
console.log(`User: ${this._user.username} experienced error in config job for object: ${objectToSync.name}, ${objectToSync.type}, ${objectToSync.id}`);
109-
let context = this._sentryService.createExtraContext('Object_to_sync', JSON.parse(JSON.stringify(objectToSync)));
110-
this._sentryService.logError(ex, context);
111104
}
112105
}
113106

@@ -123,7 +116,7 @@ export class ConfigSyncJob extends SyncJob {
123116
// even if some api operations were not ok, persist changes to the mappings - better than nothing
124117
await databaseService.updateUserMappings(this._user);
125118

126-
await databaseService.updateJobLog(this._jobLog);
119+
await this.updateJobLog(Array.from(secondaryServicesWrappersMap.values()).flatMap(wrapper => wrapper.syncedService?.errors ?? []));
127120

128121
return operationsOk;
129122
}
@@ -152,7 +145,7 @@ export class ConfigSyncJob extends SyncJob {
152145
continue;
153146
}
154147
// firstly create object in the service, then create serviceObject with newly acquired id
155-
const newObject = await this._createServiceObjectInService(serviceWrapper, objectToSync);
148+
const newObject = await serviceWrapper.syncedService.createServiceObject(objectToSync.id, objectToSync.name, objectToSync.type);
156149
mappingsObject = new MappingsObject(newObject.id, newObject.name, serviceDefinition.name, newObject.type);
157150
}
158151

@@ -189,45 +182,27 @@ export class ConfigSyncJob extends SyncJob {
189182
// mappingObject is missing, create a new one and add to mapping (maybe new service was added)
190183
// create a real object in the service and add mappingObject
191184
// firstly create object in the service, then create serviceObject with newly acquired id
192-
const newObject = await this._createServiceObjectInService(serviceWrapper, objectToSync);
185+
const newObject = await serviceWrapper.syncedService.createServiceObject(objectToSync.id, objectToSync.name, objectToSync.type);
193186
const newMappingsObject = new MappingsObject(newObject.id, newObject.name, serviceDefinition.name, newObject.type);
194187
mapping.mappingsObjects.push(newMappingsObject);
195188
} else {
196189
// scenario b), c), e)
197190
// check if mapping corresponds with real object in the service
198-
const objectBasedOnMapping = await serviceWrapper.allServiceObjects
191+
const objectBasedOnMapping = serviceWrapper.allServiceObjects
199192
.find(serviceObject => serviceObject.id === mappingsObject.id && serviceObject.type === mappingsObject.type);
200193

201194
if (!objectBasedOnMapping) {
202195
// scenario e), create new object in the service
203-
const newObject = await this._createServiceObjectInService(serviceWrapper, objectToSync);
196+
const newObject = await serviceWrapper.syncedService.createServiceObject(objectToSync.id, objectToSync.name, objectToSync.type);
204197
mappingsObject.id = newObject.id;
205198
mappingsObject.name = newObject.name;
206199
mappingsObject.lastUpdated = Date.now();
207200
} else if (objectBasedOnMapping.name !== serviceWrapper.syncedService.getFullNameForServiceObject(objectToSync)) {
208201
// scenario b)
209202
// name is incorrect => maybe mapping was outdated or/and real object was outdated
210-
let updatedObject = null;
211-
try {
212-
updatedObject = await serviceWrapper.syncedService.updateServiceObject(
213-
mappingsObject.id, new ServiceObject(objectToSync.id, objectToSync.name, objectToSync.type)
214-
);
215-
} catch (ex: any) {
216-
if (ex.status !== 400) {
217-
throw ex;
218-
}
219-
// 400 ~ maybe object already exists and cannot be updated (for example object needs to be unique - name)?
220-
// => try to find it and use it for the mapping
221-
const serviceObjectName = serviceWrapper.syncedService.getFullNameForServiceObject(new ServiceObject(objectToSync.id, objectToSync.name, objectToSync.type));
222-
updatedObject = serviceWrapper.allServiceObjects.find(serviceObject => serviceObject.name === serviceObjectName);
223-
if (!updatedObject) {
224-
const context = [
225-
this._sentryService.createExtraContext('Object_to_sync', {'id': objectToSync.id, 'name': objectToSync.name, 'type': objectToSync.type})
226-
]
227-
this._sentryService.logError(ex, context);
228-
throw ex;
229-
}
230-
}
203+
const updatedObject = await serviceWrapper.syncedService.updateServiceObject(
204+
mappingsObject.id, new ServiceObject(objectToSync.id, objectToSync.name, objectToSync.type)
205+
);
231206
// console.log(`ConfigSyncJob: Updated object ${updatedObject.name}`);
232207
mappingsObject.name = updatedObject.name;
233208
mappingsObject.lastUpdated = Date.now();
@@ -240,28 +215,4 @@ export class ConfigSyncJob extends SyncJob {
240215

241216
return true;
242217
}
243-
244-
private async _createServiceObjectInService(serviceWrapper: SyncedServiceWrapper, objectToSync: ServiceObject): Promise<ServiceObject> {
245-
let newObject;
246-
try {
247-
newObject = await serviceWrapper.syncedService.createServiceObject(objectToSync.id, objectToSync.name, objectToSync.type);
248-
} catch (ex: any) {
249-
if (ex.status !== 400) {
250-
throw ex;
251-
}
252-
// 400 ~ maybe object already exists and cannot be created (for example object needs to be unique - name)?
253-
// => try to find it and use it for the mapping
254-
const serviceObjectName = serviceWrapper.syncedService.getFullNameForServiceObject(new ServiceObject(objectToSync.id, objectToSync.name, objectToSync.type));
255-
newObject = serviceWrapper.allServiceObjects.find(serviceObject => serviceObject.name === serviceObjectName);
256-
if (!newObject) {
257-
let context = [
258-
this._sentryService.createExtraContext('Object_to_sync', {'id': objectToSync.id, 'name': objectToSync.name, 'type': objectToSync.type})
259-
]
260-
this._sentryService.logError(ex, context);
261-
throw ex;
262-
}
263-
// console.log(`ConfigSyncJob: Creating mapping, but object exists, using real object ${newObject.name}`);
264-
}
265-
return newObject;
266-
}
267218
}

src/jobs/remove_obsolete_mappings_job.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,29 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
4545
mapping.primaryObjectType == objectToRemove.type &&
4646
(mapping.primaryObjectType == 'issue' || mapping.primaryObjectType == 'project' )));
4747
}
48+
} else {
49+
await this.updateJobLog(primarySyncedService.errors);
4850
}
4951

5052
// case 2 - remove mappings with non-existing service object in primary service
5153
const mappingChunks = this._chunkArray(userMappings.filter(mapping => mapping.primaryObjectType == 'issue'), 50);
5254
for (const chunk of mappingChunks) {
53-
const issues = await primarySyncedService.getServiceObjects(chunk.map(mapping => mapping.primaryObjectId));
54-
if (issues.length !== chunk.length) {
55-
// some issues were not found - find mappings to remove
56-
const foundIssueIds = new Set(issues.map(issue => issue.id));
57-
const notFoundMappings = chunk.filter(mapping => !foundIssueIds.has(mapping.primaryObjectId));
58-
obsoleteMappings.push(...notFoundMappings);
55+
try {
56+
const issues = await primarySyncedService.getServiceObjects(chunk.map(mapping => mapping.primaryObjectId));
57+
if (issues.length !== chunk.length) {
58+
// some issues were not found - find mappings to remove
59+
const foundIssueIds = new Set(issues.map(issue => issue.id));
60+
const notFoundMappings = chunk.filter(mapping => !foundIssueIds.has(mapping.primaryObjectId));
61+
obsoleteMappings.push(...notFoundMappings);
62+
}
63+
} catch (err: any) {
64+
await this.updateJobLog(primarySyncedService.errors);
65+
// keep old behaviour
66+
// throw err;
5967
}
6068
}
6169

62-
console.log('Obsolete mappings: ', obsoleteMappings);
70+
//console.log('Obsolete mappings: ', obsoleteMappings);
6371

6472
// remove duplicates
6573
obsoleteMappings = Array.from(new Set(obsoleteMappings));
@@ -72,7 +80,9 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
7280
// persist changes in the mappings
7381
// even if some api operations were not ok, persist changes to the mappings - better than nothing
7482
await databaseService.updateUserMappings(this._user);
75-
await databaseService.updateJobLog(this._jobLog);
83+
84+
await this.updateJobLog([]);
85+
7686
return operationsOk;
7787
}
7888

@@ -90,20 +100,16 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
90100
if (!syncedService) continue;
91101
let operationOk = true;
92102
try {
93-
operationOk = await syncedService.deleteServiceObject(mappingObject.id, mappingObject.type);
103+
operationOk = await syncedService.deleteServiceObject(mappingObject.id, mappingObject.type, mappingObject.name);
94104
} catch (ex: any) {
95105
if (ex.status === 404) {
96106
// service object is missing, it is ok to delete the mapping
97107
operationOk = true;
98108
} else {
99-
const context = [
100-
this._sentryService.createExtraContext('Mapping to delete', {
101-
'id': mappingObject.id,
102-
'type': mappingObject.type
103-
})
104-
]
105-
this._sentryService.logError(ex, context);
106-
// console.error('err: ConfigSyncJob: delete; exception');
109+
operationOk &&= ex.response.ok;
110+
if (syncedService.errors.length > 0) {
111+
this._jobLog.errors.push(syncedService.errors[syncedService.errors.length - 1]);
112+
}
107113
}
108114
}
109115
operationsOk &&= operationOk;
@@ -154,6 +160,9 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
154160
const relatedTimeEntriesFromApi = await service.getTimeEntriesRelatedToMappingObjectForUser(mapping, this._user);
155161
if (!relatedTimeEntriesFromApi) {
156162
operationsOk = false;
163+
if (service.errors.length > 0) {
164+
this._jobLog.errors.push(service.errors[service.errors.length - 1]);
165+
}
157166
} else {
158167
for (const timeEntryFromApi of relatedTimeEntriesFromApi) {
159168
const foundTESO = await databaseService.getTimeEntrySyncedObjectForArchiving(timeEntryFromApi.id, primaryObjectServiceName, this._user._id);
@@ -192,6 +201,9 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
192201
await togglService.syncedService.replaceTimeEntryDescription(toggleTimeEntry, timeEntryToArchive.issueName)
193202
} catch (exception) {
194203
operationsOk = false;
204+
if (togglService.syncedService.errors.length > 0) {
205+
this._jobLog.errors.push(togglService.syncedService.errors[togglService.syncedService.errors.length - 1]);
206+
}
195207
}
196208
}
197209

@@ -201,12 +213,9 @@ export class RemoveObsoleteMappingsJob extends SyncJob {
201213
}
202214

203215
// and remove all obsolete mappings from user's mappings
204-
this._user.mappings
205-
= this._user
206-
.mappings
207-
.filter(
208-
mapping => obsoleteMappings.find(obsoleteMapping => obsoleteMapping === mapping)
209-
=== undefined) ?? [];
216+
this._user.mappings = this._user.mappings.filter(
217+
mapping => obsoleteMappings.find(obsoleteMapping => obsoleteMapping === mapping) === undefined
218+
) ?? [];
210219
}
211220
return operationsOk;
212221
}

src/jobs/sync_job.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { JobLog } from "../models/job_log";
22
import { User } from "../models/user";
33
import {SentryService} from "../shared/sentry_service";
44
import {ErrorService} from "../shared/error_service";
5+
import {Timer2TicketError} from "../models/timer2TicketError";
6+
import {databaseService} from "../shared/database_service";
57

68
export abstract class SyncJob {
79
protected _user: User;
@@ -34,4 +36,13 @@ export abstract class SyncJob {
3436
* Does the job, returns true if successfully done, false otherwise and needs to be repeated
3537
*/
3638
protected abstract _doTheJob(): Promise<boolean>;
39+
40+
protected async updateJobLog(errors: Timer2TicketError[]) : Promise<void>
41+
{
42+
this._jobLog.errors = this._jobLog.errors.concat(errors);
43+
const updated = await databaseService.updateJobLog(this._jobLog);
44+
if (updated instanceof JobLog) {
45+
this._jobLog = updated;
46+
}
47+
}
3748
}

0 commit comments

Comments
 (0)