Signed-off-by: bnechyporenko <bnechyporenko@bol.com>
This commit is contained in:
bnechyporenko
2024-01-21 12:53:14 +01:00
parent 3a7b9a08a2
commit 898f513bac
3 changed files with 75 additions and 25 deletions
@@ -41,6 +41,7 @@ import {
import { DateTime, Duration } from 'luxon';
import { TaskRecovery, TaskSpec } from '@backstage/plugin-scaffolder-common';
import { trimEventsTillLastRecovery } from './taskRecoveryHelper';
import { intervalFromNowTill } from './dbUtil';
const migrationsDir = resolvePackagePath(
'@backstage/plugin-scaffolder-backend',
@@ -294,18 +295,7 @@ export class DatabaseTaskStore implements TaskStore {
tasks: { taskId: string; recovery?: TaskRecovery }[];
}> {
const { timeoutS } = options;
let heartbeatInterval = this.db.raw(`? - interval '${timeoutS} seconds'`, [
this.db.fn.now(),
]);
if (this.db.client.config.client.includes('mysql')) {
heartbeatInterval = this.db.raw(
`date_sub(now(), interval ${timeoutS} second)`,
);
} else if (this.db.client.config.client.includes('sqlite3')) {
heartbeatInterval = this.db.raw(`datetime('now', ?)`, [
`-${timeoutS} seconds`,
]);
}
const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);
const rawRows = await this.db<RawDbTaskRow>('tasks')
.where('status', 'processing')
.andWhere('last_heartbeat_at', '<=', heartbeatInterval);
@@ -498,19 +488,7 @@ export class DatabaseTaskStore implements TaskStore {
const timeoutS = Duration.fromObject(options.timeout).as('seconds');
await this.db.transaction(async tx => {
let heartbeatInterval = this.db.raw(
`? - interval '${timeoutS} seconds'`,
[this.db.fn.now()],
);
if (this.db.client.config.client.includes('mysql')) {
heartbeatInterval = this.db.raw(
`date_sub(now(), interval ${timeoutS} second)`,
);
} else if (this.db.client.config.client.includes('sqlite3')) {
heartbeatInterval = this.db.raw(`datetime('now', ?)`, [
`-${timeoutS} seconds`,
]);
}
const heartbeatInterval = intervalFromNowTill(timeoutS, this.db);
const result = await tx<RawDbTaskRow>('tasks')
.where('status', 'processing')
@@ -0,0 +1,40 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import knexFactory, { Knex } from 'knex';
import { intervalFromNowTill } from './dbUtil';
class KnexBuilder {
public build(client: string): Knex {
return knexFactory({ client, useNullAsDefault: true });
}
}
describe('util', () => {
describe('intervalFromNowTill', () => {
const databases = [
{ client: 'sqlite3', expected: "datetime('now', '-5 seconds')" },
{ client: 'mysql', expected: 'date_sub(now(), interval 5 second)' },
{ client: 'pg', expected: "CURRENT_TIMESTAMP - interval '5 seconds'" },
];
it.each(databases)('for client $client', ({ client, expected }) => {
const knex = new KnexBuilder().build(client);
const result = intervalFromNowTill(5, knex);
expect(result.toString()).toBe(expected);
});
});
});
@@ -0,0 +1,32 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Knex } from 'knex';
export const intervalFromNowTill = (timeoutS: number, knex: Knex) => {
let heartbeatInterval = knex.raw(`? - interval '${timeoutS} seconds'`, [
knex.fn.now(),
]);
if (knex.client.config.client.includes('mysql')) {
heartbeatInterval = knex.raw(
`date_sub(now(), interval ${timeoutS} second)`,
);
} else if (knex.client.config.client.includes('sqlite3')) {
heartbeatInterval = knex.raw(`datetime('now', ?)`, [
`-${timeoutS} seconds`,
]);
}
return heartbeatInterval;
};