1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-31 00:16:47 +01:00

feat: persist client application usage (#4534)

Closes #
[1-1256](https://linear.app/unleash/issue/1-1256/backend-to-save-application-usage)

Adds client application usage persisting on upsert and bulkUpsert
functions

---------

Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
andreas-unleash 2023-08-21 14:36:31 +03:00 committed by GitHub
parent 68273da213
commit d19d97cf18
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 0 deletions

View File

@ -21,6 +21,8 @@ const COLUMNS = [
];
const TABLE = 'client_applications';
const TABLE_USAGE = 'client_applications_usage';
const mapRow: (any) => IClientApplication = (row) => ({
appName: row.app_name,
createdAt: row.created_at,
@ -57,6 +59,14 @@ const remapRow = (input) => {
return temp;
};
const remapUsageRow = (input) => {
return {
app_name: input.appName,
project: input.project || '*',
environment: input.environment || '*',
};
};
export default class ClientApplicationsStore
implements IClientApplicationsStore
{
@ -72,11 +82,21 @@ export default class ClientApplicationsStore
async upsert(details: Partial<IClientApplication>): Promise<void> {
const row = remapRow(details);
await this.db(TABLE).insert(row).onConflict('app_name').merge();
const usageRow = remapUsageRow(details);
await this.db(TABLE_USAGE)
.insert(usageRow)
.onConflict(['app_name', 'project', 'environment'])
.merge();
}
async bulkUpsert(apps: Partial<IClientApplication>[]): Promise<void> {
const rows = apps.map(remapRow);
const usageRows = apps.map(remapUsageRow);
await this.db(TABLE).insert(rows).onConflict('app_name').merge();
await this.db(TABLE_USAGE)
.insert(usageRows)
.onConflict(['app_name', 'project', 'environment'])
.merge();
}
async exists(appName: string): Promise<boolean> {

View File

@ -63,12 +63,23 @@ export default class RegisterController extends Controller {
return 'default';
}
private static extractProjectFromRequest(
req: IAuthRequest<unknown, void, ClientApplicationSchema>,
) {
const token = req.get('Authorisation');
if (token) {
return token.split(':')[0];
}
return 'default';
}
async registerClientApplication(
req: IAuthRequest<unknown, void, ClientApplicationSchema>,
res: Response<void>,
): Promise<void> {
const { body: data, ip: clientIp, user } = req;
data.environment = RegisterController.resolveEnvironment(user, data);
data.project = RegisterController.extractProjectFromRequest(req);
await this.clientInstanceService.registerClient(data, clientIp);
res.status(202).end();
}

View File

@ -91,4 +91,5 @@ export const clientRegisterSchema = joi
started: joi.date().required(),
interval: joi.number().required(),
environment: joi.string().optional(),
project: joi.string().optional(),
});

View File

@ -0,0 +1,32 @@
'use strict';
exports.up = function (db, callback) {
db.runSql(
`
DROP TABLE IF EXISTS client_applications_usage;
CREATE TABLE IF NOT EXISTS client_applications_usage (
app_name VARCHAR(255) REFERENCES client_applications(app_name) ON DELETE CASCADE,
project VARCHAR(255) NOT NULL ,
environment VARCHAR(100) NOT NULL ,
PRIMARY KEY(app_name, project, environment)
) ;
`,
callback,
);
};
exports.down = function (db, callback) {
db.runSql(
`
DROP TABLE IF EXISTS client_applications_usage;
CREATE TABLE IF NOT EXISTS client_applications_usage (
app_name VARCHAR(255) REFERENCES client_applications(app_name) ON DELETE CASCADE,
project VARCHAR(255) REFERENCES projects(id) ON DELETE CASCADE,
environment VARCHAR(100) REFERENCES environments(name) ON DELETE CASCADE,
PRIMARY KEY(app_name, project, environment)
) ;
`,
callback,
);
};