1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-08-18 13:48:58 +02:00

change update to upsert

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
andreas-unleash 2023-09-25 19:48:56 +03:00
parent 6de0414732
commit f64ba6b60c
No known key found for this signature in database
GPG Key ID: DB82A1577B38F66B
3 changed files with 72 additions and 16 deletions

View File

@ -171,24 +171,37 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
return present;
}
private upsert = (params: any) => {
const { table, object, constraint } = params;
const insert = this.db(table).insert(object);
const update = this.db.queryBuilder().update(object);
return this.db
.raw(`? ON CONFLICT ${constraint} DO ? returning *`, [
insert,
update,
])
.get('rows')
.get(0);
};
async setLastSeen(data: LastSeenInput[]): Promise<void> {
const now = new Date();
const environmentArrays = this.mapMetricDataToEnvBuckets(data);
try {
for (const env of Object.keys(environmentArrays)) {
const toggleNames = environmentArrays[env].sort();
await this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
.upsert({ last_seen_at: now })
.where('environment', env)
.whereIn(
'feature_name',
this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
.select('feature_name')
.whereIn('feature_name', toggleNames)
.forUpdate()
.skipLocked(),
);
const enhancedData = data.map((value) => ({
feature_name: value.featureName,
last_seen_at: now,
environment: value.environment,
}));
const dataToPersist: typeof enhancedData = [];
for (const input of enhancedData) {
if (await this.exists(input.feature_name)) {
dataToPersist.push(input);
}
}
try {
await this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
.insert(dataToPersist)
.onConflict(['feature_name', 'environment'])
.merge(['last_seen_at']);
} catch (err) {
this.logger.error('Could not update lastSeen, error: ', err);
}

View File

@ -58,7 +58,7 @@ export class LastSeenService {
.filter(
(clientMetric) => clientMetric.yes > 0 || clientMetric.no > 0,
)
.forEach((clientMetric) => {
.forEach(async (clientMetric) => {
const key = `${clientMetric.featureName}:${clientMetric.environment}`;
this.lastSeenToggles.set(key, {
featureName: clientMetric.featureName,

View File

@ -129,3 +129,46 @@ test('Should not update anything for 0 toggles', async () => {
service.destroy();
});
test('Should handle 1000 toggle updates', async () => {
// jest.useFakeTimers();
const service = new LastSeenService(stores, config, 30);
const time = Date.now();
for (let i = 0; i <= 1000; i++) {
await stores.featureToggleStore.create('default', { name: `tb${i}` });
}
const metrics: IClientMetricsEnv[] = [];
for (let i = 0; i < 999; i++) {
metrics.push({
featureName: `tb${i}`,
appName: 'some-App',
environment: 'default',
timestamp: new Date(time),
yes: 1,
no: 0,
});
}
metrics.push({
featureName: 'tb1000',
appName: 'some-App',
environment: 'default',
timestamp: new Date(time),
yes: 0,
no: 0,
});
service.updateLastSeen(metrics);
// bypass interval waiting
await service.store();
const t1 = await stores.featureToggleStore.get('tb1');
const t2 = await stores.featureToggleStore.get('tb1000');
expect(t2.lastSeenAt).toBeNull();
expect(t1.lastSeenAt.getTime()).toBeGreaterThanOrEqual(time);
service.destroy();
});