1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-19 17:52:45 +02:00

chore: support different etags per environment

This commit is contained in:
Gastón Fournier 2025-08-19 15:40:04 +02:00
parent 7f6b09fa1e
commit 6569d72d79
No known key found for this signature in database
GPG Key ID: AF45428626E17A8E
4 changed files with 64 additions and 43 deletions

View File

@ -359,7 +359,9 @@ export default class FeatureController extends Controller {
async calculateMeta(query: IFeatureToggleQuery): Promise<IMeta> {
// TODO: We will need to standardize this to be able to implement this a cross languages (Edge in Rust?).
const revisionId =
await this.configurationRevisionService.getMaxRevisionId();
await this.configurationRevisionService.getMaxRevisionId(
environment,
);
// TODO: We will need to standardize this to be able to implement this a cross languages (Edge in Rust?).
const queryHash = hashSum(query);

View File

@ -191,29 +191,37 @@ export class EventStore implements IEventStore {
}
}
async getMaxRevisionId(largerThan: number = 0): Promise<number> {
const stopTimer = this.metricTimer('getMaxRevisionId');
const row = await this.db(TABLE)
.max('id')
.where((builder) =>
builder
.andWhere((inner) =>
inner
.whereNotNull('feature_name')
.whereNotIn('type', [
FEATURE_CREATED,
FEATURE_TAGGED,
])
.whereNot('type', 'LIKE', 'change-%'),
)
.orWhereIn('type', [
SEGMENT_UPDATED,
FEATURE_IMPORT,
FEATURES_IMPORTED,
]),
private typeIsInteresting = (builder: Knex.QueryBuilder) =>
builder
.andWhere((inner) =>
inner
.whereNotNull('feature_name')
.whereNotIn('type', [FEATURE_CREATED, FEATURE_TAGGED])
.whereNot('type', 'LIKE', 'change-%'),
)
.andWhere('id', '>=', largerThan)
.first();
.orWhereIn('type', [
SEGMENT_UPDATED,
FEATURE_IMPORT,
FEATURES_IMPORTED,
SEGMENT_CREATED,
SEGMENT_DELETED,
]);
async getMaxRevisionId(
largerThan: number = 0,
environment?: string,
): Promise<number> {
const stopTimer = this.metricTimer('getMaxRevisionId');
const query = this.db(TABLE)
.max('id')
.where(this.typeIsInteresting)
.andWhere('id', '>=', largerThan);
if (environment) {
query.where('environment', environment);
}
const row = await query.first();
stopTimer();
return row?.max ?? 0;
}
@ -225,27 +233,11 @@ export class EventStore implements IEventStore {
.from(TABLE)
.where('id', '>', start)
.andWhere('id', '<=', end)
.andWhere((builder) =>
builder
.andWhere((inner) =>
inner
.whereNotNull('feature_name')
.whereNotIn('type', [
FEATURE_CREATED,
FEATURE_TAGGED,
]),
)
.orWhereIn('type', [
SEGMENT_UPDATED,
FEATURE_IMPORT,
FEATURES_IMPORTED,
SEGMENT_CREATED,
SEGMENT_DELETED,
]),
)
.andWhere(this.typeIsInteresting)
.orderBy('id', 'asc');
const rows = await query;
stopTimer();
return rows.map(this.rowToEvent);
}

View File

@ -18,6 +18,8 @@ export default class ConfigurationRevisionService extends EventEmitter {
private revisionId: number;
private maxRevisionId: Record<string, number> = {};
private flagResolver: IFlagResolver;
private constructor(
@ -51,7 +53,17 @@ export default class ConfigurationRevisionService extends EventEmitter {
return ConfigurationRevisionService.instance;
}
async getMaxRevisionId(): Promise<number> {
async getMaxRevisionId(environment?: string): Promise<number> {
if (environment && !this.maxRevisionId[environment]) {
await this.updateMaxEnvironmentRevisionId(environment);
}
if (
environment &&
this.maxRevisionId[environment] &&
this.maxRevisionId[environment] > 0
) {
return this.maxRevisionId[environment];
}
if (this.revisionId > 0) {
return this.revisionId;
} else {
@ -59,6 +71,18 @@ export default class ConfigurationRevisionService extends EventEmitter {
}
}
async updateMaxEnvironmentRevisionId(environment: string): Promise<number> {
const envRevisionId = await this.eventStore.getMaxRevisionId(
this.revisionId,
environment,
);
if (this.maxRevisionId[environment] < envRevisionId) {
this.maxRevisionId[environment] = envRevisionId;
}
return this.maxRevisionId[environment];
}
async updateMaxRevisionId(emit: boolean = true): Promise<number> {
if (this.flagResolver.isEnabled('disableUpdateMaxRevisionId')) {
return 0;

View File

@ -38,7 +38,10 @@ export interface IEventStore
queryParams: IQueryParam[],
options?: { withIp?: boolean },
): Promise<IEvent[]>;
getMaxRevisionId(currentMax?: number): Promise<number>;
getMaxRevisionId(
currentMax?: number,
environment?: string,
): Promise<number>;
getRevisionRange(start: number, end: number): Promise<IEvent[]>;
query(operations: IQueryOperations[]): Promise<IEvent[]>;
queryCount(operations: IQueryOperations[]): Promise<number>;