@solidxai/core 0.1.6-beta.23 → 0.1.6-beta.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entities/mq-message-queue.entity.d.ts.map +1 -1
- package/dist/entities/mq-message-queue.entity.js.map +1 -1
- package/dist/helpers/bootstrap.helper.js +1 -1
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/helpers/cors.helper.d.ts.map +1 -1
- package/dist/helpers/cors.helper.js +4 -1
- package/dist/helpers/cors.helper.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/chatter-queue-options.js +1 -1
- package/dist/jobs/chatter-queue-options.js.map +1 -1
- package/dist/jobs/chatter-queue-publisher.service.d.ts +9 -9
- package/dist/jobs/chatter-queue-publisher.service.d.ts.map +1 -1
- package/dist/jobs/chatter-queue-publisher.service.js +5 -5
- package/dist/jobs/chatter-queue-publisher.service.js.map +1 -1
- package/dist/jobs/chatter-queue-subscriber.service.d.ts +4 -4
- package/dist/jobs/chatter-queue-subscriber.service.d.ts.map +1 -1
- package/dist/jobs/chatter-queue-subscriber.service.js +11 -11
- package/dist/jobs/chatter-queue-subscriber.service.js.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.js +1 -0
- package/dist/jobs/computed-field-evaluation-queue-options.js.map +1 -1
- package/dist/jobs/database/chatter-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/chatter-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-options-database.js +10 -0
- package/dist/jobs/database/chatter-queue-options-database.js.map +1 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.js +39 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.d.ts +19 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.js +62 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.js.map +1 -0
- package/dist/services/chatter-message.service.d.ts +4 -4
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +33 -9
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.d.ts +1 -0
- package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.js +6 -1
- package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +1 -0
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +15 -4
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/request-context.service.d.ts +2 -1
- package/dist/services/request-context.service.d.ts.map +1 -1
- package/dist/services/request-context.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +8 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +8 -3
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +54 -52
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts +0 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js +3 -13
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/entities/mq-message-queue.entity.ts +8 -8
- package/src/helpers/bootstrap.helper.ts +1 -1
- package/src/helpers/cors.helper.ts +5 -1
- package/src/interfaces.ts +1 -0
- package/src/jobs/chatter-queue-options.ts +1 -1
- package/src/jobs/chatter-queue-publisher.service.ts +11 -11
- package/src/jobs/chatter-queue-subscriber.service.ts +13 -8
- package/src/jobs/computed-field-evaluation-queue-options.ts +1 -0
- package/src/jobs/database/chatter-queue-options-database.ts +9 -0
- package/src/jobs/database/chatter-queue-publisher-database.service.ts +24 -0
- package/src/jobs/database/chatter-queue-subscriber-database.service.ts +53 -0
- package/src/services/chatter-message.service.ts +41 -9
- package/src/services/queues/rabbitmq-publisher.service.ts +8 -2
- package/src/services/queues/rabbitmq-subscriber.service.ts +16 -5
- package/src/services/request-context.service.ts +2 -1
- package/src/solid-core.module.ts +8 -2
- package/src/subscribers/audit.subscriber.ts +59 -224
- package/src/subscribers/created-by-updated-by.subscriber.ts +22 -16
- package/logs_load_testing +0 -49
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import { Injectable, Scope } from '@nestjs/common';
|
|
1
|
+
import { Injectable, Logger, Scope } from '@nestjs/common';
|
|
2
2
|
import { lowerFirst } from 'src/helpers/string.helper';
|
|
3
3
|
import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
4
4
|
import { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type DeferredCall =
|
|
9
|
-
| { kind: 'insert'; args: Parameters<ChatterMessageService['postAuditMessageOnInsert']> }
|
|
10
|
-
| { kind: 'update'; args: Parameters<ChatterMessageService['postAuditMessageOnUpdate']> }
|
|
11
|
-
| { kind: 'delete'; args: Parameters<ChatterMessageService['postAuditMessageOnDelete']> };
|
|
5
|
+
import { AuditQueuePayload } from 'src/jobs/chatter-queue-publisher.service';
|
|
6
|
+
import { RequestContextService } from 'src/services/request-context.service';
|
|
7
|
+
import { PublisherFactory } from 'src/services/queues/publisher-factory.service';
|
|
12
8
|
|
|
13
9
|
@Injectable({scope: Scope.TRANSIENT})
|
|
14
|
-
// @EventSubscriber()
|
|
15
10
|
export class AuditSubscriber implements EntitySubscriberInterface {
|
|
11
|
+
private readonly logger = new Logger(AuditSubscriber.name);
|
|
16
12
|
private dataSource: DataSource;
|
|
17
13
|
constructor(
|
|
18
|
-
private readonly
|
|
14
|
+
private readonly publisherFactory: PublisherFactory<AuditQueuePayload>,
|
|
19
15
|
private readonly solidRegistry: SolidRegistry,
|
|
16
|
+
private readonly requestContextService: RequestContextService,
|
|
20
17
|
) { }
|
|
21
18
|
|
|
22
19
|
bindToDataSource(dataSource: DataSource) {
|
|
@@ -25,12 +22,12 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
// Per-transaction buffer (auto-GC when queryRunner is gone)
|
|
28
|
-
private perTxn = new WeakMap<any,
|
|
25
|
+
private perTxn = new WeakMap<any, AuditQueuePayload[]>();
|
|
29
26
|
|
|
30
|
-
private enqueue(event: { queryRunner: any },
|
|
27
|
+
private enqueue(event: { queryRunner: any }, payload: AuditQueuePayload) {
|
|
31
28
|
const qr = event.queryRunner;
|
|
32
29
|
const arr = this.perTxn.get(qr) ?? [];
|
|
33
|
-
arr.push(
|
|
30
|
+
arr.push(payload);
|
|
34
31
|
this.perTxn.set(qr, arr);
|
|
35
32
|
}
|
|
36
33
|
|
|
@@ -38,43 +35,48 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
38
35
|
return this.solidRegistry.isAuditableModel(lowerFirst(metadata.name));
|
|
39
36
|
}
|
|
40
37
|
|
|
38
|
+
private activeUserId(): number | null {
|
|
39
|
+
return this.requestContextService.getActiveUser()?.sub ?? null;
|
|
40
|
+
}
|
|
41
|
+
|
|
41
42
|
async afterInsert(event: InsertEvent<any>) {
|
|
42
|
-
if (this.shouldTrackAudit(event.metadata))
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
44
|
+
this.enqueue(event, {
|
|
45
|
+
eventType: 'insert',
|
|
46
|
+
modelName: event.metadata.name,
|
|
47
|
+
entityId: event.entity?.id ?? null,
|
|
48
|
+
occurredAt: new Date().toISOString(),
|
|
49
|
+
after: event.entity ?? null,
|
|
50
|
+
userId: this.activeUserId(),
|
|
51
|
+
});
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
async afterUpdate(event: UpdateEvent<any>) {
|
|
52
|
-
if (this.shouldTrackAudit(event.metadata))
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
56
|
+
this.enqueue(event, {
|
|
57
|
+
eventType: 'update',
|
|
58
|
+
modelName: event.metadata.name,
|
|
59
|
+
entityId: event.entity?.id ?? null,
|
|
60
|
+
occurredAt: new Date().toISOString(),
|
|
61
|
+
after: event.entity ?? null,
|
|
62
|
+
// databaseEntity is only populated when the entity was fetched first (save() path).
|
|
63
|
+
// QueryBuilder update() leaves this undefined; postAuditMessageOnUpdate guards for it.
|
|
64
|
+
before: event.databaseEntity ?? null,
|
|
65
|
+
updatedColumnNames: (event.updatedColumns ?? []).map(c => c.propertyName),
|
|
66
|
+
userId: this.activeUserId(),
|
|
67
|
+
});
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
async afterRemove(event: RemoveEvent<any>) {
|
|
67
|
-
if (this.shouldTrackAudit(event.metadata))
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
});
|
|
77
|
-
}
|
|
71
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
72
|
+
this.enqueue(event, {
|
|
73
|
+
eventType: 'delete',
|
|
74
|
+
modelName: event.metadata.name,
|
|
75
|
+
entityId: event.databaseEntity?.id ?? null,
|
|
76
|
+
occurredAt: new Date().toISOString(),
|
|
77
|
+
before: event.databaseEntity,
|
|
78
|
+
userId: this.activeUserId(),
|
|
79
|
+
});
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
// --------- transaction lifecycle ----------
|
|
@@ -82,191 +84,24 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
82
84
|
const batch = this.perTxn.get(event.queryRunner) ?? [];
|
|
83
85
|
this.perTxn.delete(event.queryRunner);
|
|
84
86
|
|
|
85
|
-
// Now
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
// Now outside the DB transaction — safe to publish to the queue.
|
|
88
|
+
// allSettled: publish in parallel; a single failure does not block the rest.
|
|
89
|
+
const results = await Promise.allSettled(
|
|
90
|
+
batch.map(payload => this.publisherFactory.publish({ payload }, 'ChatterQueuePublisher'))
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
results.forEach((result, i) => {
|
|
94
|
+
if (result.status === 'rejected') {
|
|
95
|
+
this.logger.error(
|
|
96
|
+
`Failed to publish audit event for ${batch[i].modelName}#${batch[i].entityId}`,
|
|
97
|
+
result.reason,
|
|
98
|
+
);
|
|
96
99
|
}
|
|
97
|
-
}
|
|
100
|
+
});
|
|
98
101
|
}
|
|
99
102
|
|
|
100
103
|
afterTransactionRollback(event: { queryRunner: any }) {
|
|
101
|
-
// Drop buffered
|
|
104
|
+
// Drop buffered payloads; the write never happened.
|
|
102
105
|
this.perTxn.delete(event.queryRunner);
|
|
103
106
|
}
|
|
104
107
|
}
|
|
105
|
-
|
|
106
|
-
// import { DataSource, EntityMetadata, EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
|
|
107
|
-
// import { Injectable } from '@nestjs/common';
|
|
108
|
-
// import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
|
109
|
-
// import { Repository } from 'typeorm';
|
|
110
|
-
// import { ModelMetadata } from '../entities/model-metadata.entity';
|
|
111
|
-
// import { lowerFirst } from 'src/helpers/string.helper';
|
|
112
|
-
// import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
113
|
-
// import { ChatterMessagePayload } from 'src/jobs/chatter-queue-publisher.service';
|
|
114
|
-
// import { RequestContextService } from 'src/services/request-context.service';
|
|
115
|
-
// import { PublisherFactory } from 'src/services/queues/publisher-factory.service';
|
|
116
|
-
|
|
117
|
-
// @EventSubscriber()
|
|
118
|
-
// @Injectable()
|
|
119
|
-
// export class AuditSubscriber implements EntitySubscriberInterface {
|
|
120
|
-
// private perTxn = new WeakMap<any, ChatterMessagePayload[]>();
|
|
121
|
-
|
|
122
|
-
// constructor(
|
|
123
|
-
// @InjectDataSource() private readonly dataSource: DataSource,
|
|
124
|
-
// @InjectRepository(ModelMetadata) private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
125
|
-
// private readonly modelMetadataHelperService: ModelMetadataHelperService,
|
|
126
|
-
// private readonly requestContext: RequestContextService,
|
|
127
|
-
// private readonly publisherFactory: PublisherFactory<any>
|
|
128
|
-
// ) {
|
|
129
|
-
// this.dataSource.subscribers.push(this);
|
|
130
|
-
// }
|
|
131
|
-
|
|
132
|
-
// // --- small cache to avoid metadata queries on every row ---
|
|
133
|
-
// private modelCache = new Map<string, { enable: boolean; fields: Array<{ name: string; enableAuditTracking: boolean; type: string; relationType?: string }>; ts: number }>();
|
|
134
|
-
// private cacheTTLms = 60_000;
|
|
135
|
-
|
|
136
|
-
// private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<{ enable: boolean; auditFields?: string[] }> {
|
|
137
|
-
// const key = metadata.name;
|
|
138
|
-
// const now = Date.now();
|
|
139
|
-
// const cached = this.modelCache.get(key);
|
|
140
|
-
// if (cached && (now - cached.ts) < this.cacheTTLms) {
|
|
141
|
-
// if (!cached.enable) return { enable: false };
|
|
142
|
-
// const fields = cached.fields.filter(f =>
|
|
143
|
-
// f.enableAuditTracking &&
|
|
144
|
-
// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&
|
|
145
|
-
// !(f.type === 'relation' && f.relationType === 'one-to-many')
|
|
146
|
-
// );
|
|
147
|
-
// const present = fields.map(f => f.name).filter(n => entity?.[n] !== undefined);
|
|
148
|
-
// return { enable: present.length > 0, auditFields: present };
|
|
149
|
-
// }
|
|
150
|
-
|
|
151
|
-
// const model = await this.modelMetadataRepo.findOne({
|
|
152
|
-
// where: { singularName: lowerFirst(metadata.name) },
|
|
153
|
-
// relations: { fields: true, module: true },
|
|
154
|
-
// });
|
|
155
|
-
// const enable = !!model?.enableAuditTracking;
|
|
156
|
-
// const fields = model?.fields ?? [];
|
|
157
|
-
// this.modelCache.set(key, { enable, fields, ts: now });
|
|
158
|
-
|
|
159
|
-
// if (!enable) return { enable: false };
|
|
160
|
-
// const filtered = fields.filter(f =>
|
|
161
|
-
// f.enableAuditTracking &&
|
|
162
|
-
// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&
|
|
163
|
-
// !(f.type === 'relation' && f.relationType === 'one-to-many')
|
|
164
|
-
// );
|
|
165
|
-
// const present = filtered.map(f => f.name).filter(n => entity?.[n] !== undefined);
|
|
166
|
-
// return { enable: present.length > 0, auditFields: present };
|
|
167
|
-
// }
|
|
168
|
-
|
|
169
|
-
// private push(event: { queryRunner: any }, msg: ChatterMessagePayload) {
|
|
170
|
-
// const arr = this.perTxn.get(event.queryRunner) ?? [];
|
|
171
|
-
// arr.push(msg);
|
|
172
|
-
// this.perTxn.set(event.queryRunner, arr);
|
|
173
|
-
// }
|
|
174
|
-
|
|
175
|
-
// async afterInsert(event: InsertEvent<any>) {
|
|
176
|
-
// if (!event.entity) return;
|
|
177
|
-
// const enable = await this.shouldTrackAudit(event.entity, event.metadata);
|
|
178
|
-
// if (!enable) return;
|
|
179
|
-
|
|
180
|
-
// const payload: ChatterMessagePayload = {
|
|
181
|
-
// eventType: 'insert',
|
|
182
|
-
// model: event.metadata.name,
|
|
183
|
-
// entityId: String(event.entity.id ?? event.entity.uuid ?? ''),
|
|
184
|
-
// occurredAt: new Date().toISOString(),
|
|
185
|
-
// after: this.safeCopy(event.entity),
|
|
186
|
-
// userId: this.getUserId(),
|
|
187
|
-
// };
|
|
188
|
-
// this.push(event, payload);
|
|
189
|
-
// }
|
|
190
|
-
|
|
191
|
-
// async afterUpdate(event: UpdateEvent<any>) {
|
|
192
|
-
// // Updated entity may be null if you used raw query; fall back to databaseEntity
|
|
193
|
-
// const current = event.entity ?? {};
|
|
194
|
-
// const before = event.databaseEntity ?? {};
|
|
195
|
-
// const { enable, auditFields } = await this.shouldTrackAudit(current, event.metadata);
|
|
196
|
-
// if (!enable) return;
|
|
197
|
-
|
|
198
|
-
// const changedCols = (event.updatedColumns || []).map(c => c.propertyName);
|
|
199
|
-
// const payload: ChatterMessagePayload = {
|
|
200
|
-
// eventType: 'update',
|
|
201
|
-
// model: event.metadata.name,
|
|
202
|
-
// entityId: String((current as any).id ?? (before as any).id ?? ''),
|
|
203
|
-
// occurredAt: new Date().toISOString(),
|
|
204
|
-
// before: this.pick(before, auditFields || changedCols),
|
|
205
|
-
// after: this.pick(current, auditFields || changedCols),
|
|
206
|
-
// diff: changedCols,
|
|
207
|
-
// userId: this.getUserId(),
|
|
208
|
-
// };
|
|
209
|
-
// this.push(event, payload);
|
|
210
|
-
// }
|
|
211
|
-
|
|
212
|
-
// async afterRemove(event: RemoveEvent<any>) {
|
|
213
|
-
// const base = event.entity ?? event.databaseEntity;
|
|
214
|
-
// if (!base) return;
|
|
215
|
-
|
|
216
|
-
// const { enable } = await this.shouldTrackAudit(base, event.metadata);
|
|
217
|
-
// if (!enable) return;
|
|
218
|
-
|
|
219
|
-
// const payload: ChatterMessagePayload = {
|
|
220
|
-
// eventType: 'delete',
|
|
221
|
-
// model: event.metadata.name,
|
|
222
|
-
// entityId: String((base as any).id ?? ''),
|
|
223
|
-
// occurredAt: new Date().toISOString(),
|
|
224
|
-
// before: this.safeCopy(base),
|
|
225
|
-
// userId: this.getUserId(),
|
|
226
|
-
// };
|
|
227
|
-
// this.push(event, payload);
|
|
228
|
-
// }
|
|
229
|
-
|
|
230
|
-
// // Publish AFTER the transaction commits -> no idle-in-transaction
|
|
231
|
-
// async afterTransactionCommit(event: { queryRunner: any }) {
|
|
232
|
-
// const batch = this.perTxn.get(event.queryRunner) ?? [];
|
|
233
|
-
// this.perTxn.delete(event.queryRunner);
|
|
234
|
-
// for (const msg of batch) {
|
|
235
|
-
// try {
|
|
236
|
-
// await this.publisherFactory.publish({ payload: msg, parentEntity: msg.model, parentEntityId: msg.entityId }, 'ChatterQueuePublisher');
|
|
237
|
-
// } catch (err) {
|
|
238
|
-
// // log + optionally send to a DLQ or retry queue
|
|
239
|
-
// // do NOT throw; commit already happened
|
|
240
|
-
// // your RabbitMqPublisher likely tracks failures in MqMessage tables anyway
|
|
241
|
-
// }
|
|
242
|
-
// }
|
|
243
|
-
// }
|
|
244
|
-
|
|
245
|
-
// afterTransactionRollback(event: { queryRunner: any }) {
|
|
246
|
-
// this.perTxn.delete(event.queryRunner);
|
|
247
|
-
// }
|
|
248
|
-
|
|
249
|
-
// // --- small helpers to keep payloads JSON-safe and small ---
|
|
250
|
-
// private safeCopy(obj: any) {
|
|
251
|
-
// try {
|
|
252
|
-
// return JSON.parse(JSON.stringify(obj));
|
|
253
|
-
// } catch {
|
|
254
|
-
// return {}; // strip circular refs
|
|
255
|
-
// }
|
|
256
|
-
// }
|
|
257
|
-
|
|
258
|
-
// private pick(obj: any, keys: string[]) {
|
|
259
|
-
// const out: any = {};
|
|
260
|
-
// for (const k of keys) out[k] = obj?.[k];
|
|
261
|
-
// return this.safeCopy(out);
|
|
262
|
-
// }
|
|
263
|
-
|
|
264
|
-
// private getUserId(): string | null {
|
|
265
|
-
|
|
266
|
-
// const activeUser = this.requestContext.getActiveUser();
|
|
267
|
-
// if (activeUser?.sub)
|
|
268
|
-
// return String(activeUser.sub);
|
|
269
|
-
// }
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
// }
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Injectable, Scope } from "@nestjs/common";
|
|
2
2
|
import { InjectDataSource } from "@nestjs/typeorm";
|
|
3
|
-
import { User } from "src/entities/user.entity";
|
|
4
|
-
import { ActiveUserData } from "src/interfaces/active-user-data.interface";
|
|
5
3
|
import { RequestContextService } from "src/services/request-context.service";
|
|
6
|
-
import { DataSource, EntitySubscriberInterface,
|
|
4
|
+
import { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from "typeorm";
|
|
7
5
|
|
|
8
|
-
@Injectable({scope: Scope.TRANSIENT})
|
|
6
|
+
@Injectable({ scope: Scope.TRANSIENT })
|
|
9
7
|
// @EventSubscriber()
|
|
10
8
|
export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
11
9
|
private dataSource: DataSource;
|
|
@@ -30,7 +28,7 @@ export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
|
30
28
|
await this.stampUserField(event, false);
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
private async stampUserField(event: InsertEvent<any> | UpdateEvent<any>, isInsert: boolean){
|
|
31
|
+
private async stampUserField(event: InsertEvent<any> | UpdateEvent<any>, isInsert: boolean) {
|
|
34
32
|
if (!event.entity) {
|
|
35
33
|
return;
|
|
36
34
|
}
|
|
@@ -40,21 +38,29 @@ export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
const loadedUser = await this.loadUser(activeUserOrUndefined as unknown as ActiveUserData);
|
|
41
|
+
// const loadedUser = await this.loadUser(activeUserOrUndefined as unknown as ActiveUserData);
|
|
42
|
+
// if (isInsert) {
|
|
43
|
+
// event.entity.createdBy = loadedUser?.id;
|
|
44
|
+
// event.entity.updatedBy = loadedUser?.id; // For insert, we set both createdBy and updatedBy to the same user
|
|
45
|
+
// }
|
|
46
|
+
// else {
|
|
47
|
+
// event.entity.updatedBy = loadedUser?.id;
|
|
48
|
+
// }
|
|
49
|
+
|
|
44
50
|
if (isInsert) {
|
|
45
|
-
event.entity.createdBy =
|
|
46
|
-
event.entity.updatedBy =
|
|
51
|
+
event.entity.createdBy = activeUserOrUndefined?.sub;
|
|
52
|
+
event.entity.updatedBy = activeUserOrUndefined?.sub; // For insert, we set both createdBy and updatedBy to the same user
|
|
47
53
|
}
|
|
48
54
|
else {
|
|
49
|
-
event.entity.updatedBy =
|
|
55
|
+
event.entity.updatedBy = activeUserOrUndefined?.sub;
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
private async loadUser(activeUser: ActiveUserData): Promise<User> {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
59
|
+
// private async loadUser(activeUser: ActiveUserData): Promise<User> {
|
|
60
|
+
// const userRepo = this.defaultDataSource.getRepository(User); // Assuming 'User' is the entity name for users in your application
|
|
61
|
+
// const loadedUser = await userRepo.findOne({
|
|
62
|
+
// where: { id: activeUser.sub }, // Assuming 'sub' is the user ID in the JWT token
|
|
63
|
+
// });
|
|
64
|
+
// return loadedUser;;
|
|
65
|
+
// }
|
|
60
66
|
}
|
package/logs_load_testing
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
[2026-04-01T11:32:43.795Z] ERROR: [200 OK] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly 59891ms
|
|
2
|
-
[2026-04-01T11:32:43.795Z] ERROR: [500 Internal Server Error] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly [code=solidx-unknown-error]
|
|
3
|
-
[2026-04-01T11:32:43.795Z] ERROR: QueryFailedError: Connection terminated unexpectedly
|
|
4
|
-
at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
|
|
5
|
-
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
|
|
6
|
-
at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
|
|
7
|
-
at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
|
|
8
|
-
at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
|
|
9
|
-
at async SelectQueryBuilder.getOne (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1698:25)
|
|
10
|
-
at async AuthenticationService.findUserForLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:725:22)
|
|
11
|
-
at async AuthenticationService.otpConfirmLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:821:22)
|
|
12
|
-
[2026-04-01T11:32:43.796Z] ERROR: [200 OK] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly 59912ms
|
|
13
|
-
[2026-04-01T11:32:43.796Z] ERROR: [500 Internal Server Error] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly [code=solidx-unknown-error]
|
|
14
|
-
[2026-04-01T11:32:43.796Z] ERROR: QueryFailedError: Connection terminated unexpectedly
|
|
15
|
-
at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
|
|
16
|
-
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
|
|
17
|
-
at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
|
|
18
|
-
at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
|
|
19
|
-
at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
|
|
20
|
-
at async SelectQueryBuilder.getOne (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1698:25)
|
|
21
|
-
at async AuthenticationService.findUserForLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:725:22)
|
|
22
|
-
at async AuthenticationService.otpConfirmLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:821:22)
|
|
23
|
-
[2026-04-01T11:32:43.797Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
|
|
24
|
-
[2026-04-01T11:32:43.797Z] ERROR: QueryFailedError: Connection terminated unexpectedly
|
|
25
|
-
at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
|
|
26
|
-
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
|
|
27
|
-
at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
|
|
28
|
-
at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
|
|
29
|
-
at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
|
|
30
|
-
at async SelectQueryBuilder.getMany (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1761:25)
|
|
31
|
-
at async AuthenticationGuard.canActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/guards/authentication.guard.ts:55:36)
|
|
32
|
-
at async GuardsConsumer.tryActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/guards/guards-consumer.js:16:17)
|
|
33
|
-
at async canActivateFn (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:135:33)
|
|
34
|
-
at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:42:31
|
|
35
|
-
at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-proxy.js:9:17
|
|
36
|
-
[2026-04-01T11:32:43.798Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
|
|
37
|
-
[2026-04-01T11:32:43.798Z] ERROR: QueryFailedError: Connection terminated unexpectedly
|
|
38
|
-
at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
|
|
39
|
-
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
|
|
40
|
-
at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
|
|
41
|
-
at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
|
|
42
|
-
at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
|
|
43
|
-
at async SelectQueryBuilder.getMany (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1761:25)
|
|
44
|
-
at async AuthenticationGuard.canActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/guards/authentication.guard.ts:55:36)
|
|
45
|
-
at async GuardsConsumer.tryActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/guards/guards-consumer.js:16:17)
|
|
46
|
-
at async canActivateFn (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:135:33)
|
|
47
|
-
at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:42:31
|
|
48
|
-
at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-proxy.js:9:17
|
|
49
|
-
[2026-04-01T11:32:43.799Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
|