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:
parent
6de0414732
commit
f64ba6b60c
@ -171,24 +171,37 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
|
|||||||
return present;
|
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> {
|
async setLastSeen(data: LastSeenInput[]): Promise<void> {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const environmentArrays = this.mapMetricDataToEnvBuckets(data);
|
const enhancedData = data.map((value) => ({
|
||||||
try {
|
feature_name: value.featureName,
|
||||||
for (const env of Object.keys(environmentArrays)) {
|
last_seen_at: now,
|
||||||
const toggleNames = environmentArrays[env].sort();
|
environment: value.environment,
|
||||||
await this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
|
}));
|
||||||
.upsert({ last_seen_at: now })
|
const dataToPersist: typeof enhancedData = [];
|
||||||
.where('environment', env)
|
for (const input of enhancedData) {
|
||||||
.whereIn(
|
if (await this.exists(input.feature_name)) {
|
||||||
'feature_name',
|
dataToPersist.push(input);
|
||||||
this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
|
|
||||||
.select('feature_name')
|
|
||||||
.whereIn('feature_name', toggleNames)
|
|
||||||
.forUpdate()
|
|
||||||
.skipLocked(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE)
|
||||||
|
.insert(dataToPersist)
|
||||||
|
.onConflict(['feature_name', 'environment'])
|
||||||
|
.merge(['last_seen_at']);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.error('Could not update lastSeen, error: ', err);
|
this.logger.error('Could not update lastSeen, error: ', err);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ export class LastSeenService {
|
|||||||
.filter(
|
.filter(
|
||||||
(clientMetric) => clientMetric.yes > 0 || clientMetric.no > 0,
|
(clientMetric) => clientMetric.yes > 0 || clientMetric.no > 0,
|
||||||
)
|
)
|
||||||
.forEach((clientMetric) => {
|
.forEach(async (clientMetric) => {
|
||||||
const key = `${clientMetric.featureName}:${clientMetric.environment}`;
|
const key = `${clientMetric.featureName}:${clientMetric.environment}`;
|
||||||
this.lastSeenToggles.set(key, {
|
this.lastSeenToggles.set(key, {
|
||||||
featureName: clientMetric.featureName,
|
featureName: clientMetric.featureName,
|
||||||
|
@ -129,3 +129,46 @@ test('Should not update anything for 0 toggles', async () => {
|
|||||||
|
|
||||||
service.destroy();
|
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();
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user