mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(core): Fix sorting of executions not working on postgres and mysql (#15423)
This commit is contained in:
@@ -1048,13 +1048,32 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
|||||||
subQuery.leftJoin('execution.annotation', 'annotation');
|
subQuery.leftJoin('execution.annotation', 'annotation');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.manager
|
const qb = this.manager
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select(['e.*', 'ate.id AS "annotation_tags_id"', 'ate.name AS "annotation_tags_name"'])
|
.select(['e.*', 'ate.id AS "annotation_tags_id"', 'ate.name AS "annotation_tags_name"'])
|
||||||
.from(`(${subQuery.getQuery()})`, 'e')
|
.from(`(${subQuery.getQuery()})`, 'e')
|
||||||
.setParameters(subQuery.getParameters())
|
.setParameters(subQuery.getParameters())
|
||||||
.leftJoin(AnnotationTagMapping, 'atm', 'atm.annotationId = e.annotation_id')
|
.leftJoin(AnnotationTagMapping, 'atm', 'atm.annotationId = e.annotation_id')
|
||||||
.leftJoin(AnnotationTagEntity, 'ate', 'ate.id = atm.tagId');
|
.leftJoin(AnnotationTagEntity, 'ate', 'ate.id = atm.tagId');
|
||||||
|
|
||||||
|
// Sort the final result after the joins again, because there is no
|
||||||
|
// guarantee that the order is unchanged after performing joins. Especially
|
||||||
|
// postgres and MySQL returned to the natural order again, listing
|
||||||
|
// executions in the order they were created.
|
||||||
|
if (query.kind === 'range') {
|
||||||
|
if (query.order?.startedAt === 'DESC') {
|
||||||
|
const table = qb.escape('e');
|
||||||
|
const startedAt = qb.escape('startedAt');
|
||||||
|
const createdAt = qb.escape('createdAt');
|
||||||
|
qb.orderBy({ [`COALESCE(${table}.${startedAt}, ${table}.${createdAt})`]: 'DESC' });
|
||||||
|
} else if (query.order?.top) {
|
||||||
|
qb.orderBy(`(CASE WHEN e.status = '${query.order.top}' THEN 0 ELSE 1 END)`);
|
||||||
|
} else {
|
||||||
|
qb.orderBy({ 'e.id': 'DESC' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qb;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllIds() {
|
async getAllIds() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ExecutionRepository } from '@n8n/db';
|
import { ExecutionRepository } from '@n8n/db';
|
||||||
import { Container } from '@n8n/di';
|
import { Container } from '@n8n/di';
|
||||||
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
import { createExecution } from '@test-integration/db/executions';
|
import { createExecution } from '@test-integration/db/executions';
|
||||||
import { createWorkflow } from '@test-integration/db/workflows';
|
import { createWorkflow } from '@test-integration/db/workflows';
|
||||||
@@ -23,12 +24,30 @@ describe('UserRepository', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('findManyByRangeQuery', () => {
|
describe('findManyByRangeQuery', () => {
|
||||||
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
|
test('sort by `createdAt` if `startedAt` is null', async () => {
|
||||||
test.skip('sort by `createdAt` if `startedAt` is null', async () => {
|
const now = DateTime.utc();
|
||||||
const workflow = await createWorkflow();
|
const workflow = await createWorkflow();
|
||||||
const execution1 = await createExecution({}, workflow);
|
const execution1 = await createExecution(
|
||||||
const execution2 = await createExecution({ startedAt: null }, workflow);
|
{
|
||||||
const execution3 = await createExecution({}, workflow);
|
createdAt: now.plus({ minute: 1 }).toJSDate(),
|
||||||
|
startedAt: now.plus({ minute: 1 }).toJSDate(),
|
||||||
|
},
|
||||||
|
workflow,
|
||||||
|
);
|
||||||
|
const execution2 = await createExecution(
|
||||||
|
{
|
||||||
|
createdAt: now.plus({ minute: 2 }).toJSDate(),
|
||||||
|
startedAt: null,
|
||||||
|
},
|
||||||
|
workflow,
|
||||||
|
);
|
||||||
|
const execution3 = await createExecution(
|
||||||
|
{
|
||||||
|
createdAt: now.plus({ minute: 3 }).toJSDate(),
|
||||||
|
startedAt: now.plus({ minute: 3 }).toJSDate(),
|
||||||
|
},
|
||||||
|
workflow,
|
||||||
|
);
|
||||||
|
|
||||||
const executions = await executionRepository.findManyByRangeQuery({
|
const executions = await executionRepository.findManyByRangeQuery({
|
||||||
workflowId: workflow.id,
|
workflowId: workflow.id,
|
||||||
|
|||||||
@@ -32,13 +32,23 @@ export async function createExecution(
|
|||||||
>,
|
>,
|
||||||
workflow: IWorkflowBase,
|
workflow: IWorkflowBase,
|
||||||
) {
|
) {
|
||||||
const { data, finished, mode, startedAt, stoppedAt, waitTill, status, deletedAt, metadata } =
|
const {
|
||||||
attributes;
|
data,
|
||||||
|
finished,
|
||||||
|
mode,
|
||||||
|
startedAt,
|
||||||
|
stoppedAt,
|
||||||
|
waitTill,
|
||||||
|
status,
|
||||||
|
deletedAt,
|
||||||
|
metadata,
|
||||||
|
createdAt,
|
||||||
|
} = attributes;
|
||||||
|
|
||||||
const execution = await Container.get(ExecutionRepository).save({
|
const execution = await Container.get(ExecutionRepository).save({
|
||||||
finished: finished ?? true,
|
finished: finished ?? true,
|
||||||
mode: mode ?? 'manual',
|
mode: mode ?? 'manual',
|
||||||
createdAt: new Date(),
|
createdAt: createdAt ?? new Date(),
|
||||||
startedAt: startedAt === undefined ? new Date() : startedAt,
|
startedAt: startedAt === undefined ? new Date() : startedAt,
|
||||||
...(workflow !== undefined && { workflowId: workflow.id }),
|
...(workflow !== undefined && { workflowId: workflow.id }),
|
||||||
stoppedAt: stoppedAt ?? new Date(),
|
stoppedAt: stoppedAt ?? new Date(),
|
||||||
|
|||||||
Reference in New Issue
Block a user