From 788ef47c08c8c7b1c7c5dff87e66e21eb52e9d9f Mon Sep 17 00:00:00 2001 From: Jonathan Griffe Date: Fri, 29 Oct 2021 14:17:55 +0200 Subject: [PATCH] fix: fix compositions sorting --- src/messages/api.js | 12 +++-- src/messages/parsing.js | 79 +++++++++++++++++++++++++----- src/messages/utils.js | 14 ++++++ tests/unit/api.spec.js | 105 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 14 deletions(-) diff --git a/src/messages/api.js b/src/messages/api.js index bf3841ee..2c8dd04a 100644 --- a/src/messages/api.js +++ b/src/messages/api.js @@ -1,4 +1,5 @@ import { parseMessages } from '@/messages/parsing'; +import utils from '@/messages/utils'; const axios = require('axios'); @@ -17,9 +18,14 @@ const parseArgs = rawMessage => { const getMessages = args => { const url = '/messages/states'; - return axios - .post(url, args) - .then(res => ({ ...parseMessages(res.data.data), count: res.data.count })); + return axios.post(url, args).then(res => ({ + ...parseMessages( + res.data.data, + args.sort_column ? utils.underScoreToCamelCase(args.sort_column) : 'enqueuedDatetime', + args.sort_direction || 'desc' + ), + count: res.data.count + })); }; const cancelMessage = messageId => { diff --git a/src/messages/parsing.js b/src/messages/parsing.js index 04729215..f78f9980 100644 --- a/src/messages/parsing.js +++ b/src/messages/parsing.js @@ -156,14 +156,15 @@ function addDetails(composition) { if (composition.compositionType === 'pipeline') { composition.startedDatetime = composition.messages[0].startedDatetime; } else { - const datetime = composition.messages.reduce( - (count, { startedDatetime }) => Math.min(count, startedDatetime || Infinity), - Infinity - ); + const datetime = Math.min(...composition.messages.map(msg => msg.startedDatetime || Infinity)); if (datetime !== Infinity) { composition.startedDatetime = new Date(datetime); } } + // add Enqueued datetime + composition.enqueuedDatetime = new Date( + Math.min(...composition.messages.map(msg => msg.enqueuedDatetime || Infinity)) + ); // add Wait time composition.waitTime = composition.messages.reduce( (count, { waitTime }) => count + (waitTime || 0), @@ -369,16 +370,70 @@ function assembleComposition(compositionMsgs) { return group; } +/** + * Sorts the assembled compositions by column + * @param array + * @param sortColumn + * @param sortDirection + * @returns {*} + */ +function sortByColumn(array, sortColumn, sortDirection) { + function compareByColumn(a, b) { + let value; + if (a[sortColumn] < b[sortColumn]) { + value = 1; + } else { + value = -1; + } + if (sortDirection === 'desc') { + value *= -1; + } + return value; + } + return array.sort(compareByColumn); +} + +/** + * Merge the messages and compositions while keeping them sorted by a column + * @param messages + * @param compositions + * @param sortColumn + * @param sortDirection + * @returns {*} + */ +function insertByColumn(messages, compositions, sortColumn, sortDirection) { + let index = 0; + while (compositions.length > 0) { + if ( + index === messages.length || + (sortDirection === 'asc' && + compositions[0][sortColumn] != null && + (messages[index][sortColumn] == null || + messages[index][sortColumn] > compositions[0][sortColumn])) || + (sortDirection === 'desc' && + (compositions[0][sortColumn] == null || + (messages[index][sortColumn] != null && + messages[index][sortColumn] < compositions[0][sortColumn]))) + ) { + messages.splice(index, 0, compositions.splice(0, 1)[0]); + } + index += 1; + } + return messages; +} + /** * Parse Messages, regroup them into their compositions and add computed properties such as waitTime. * @param data + * @param sortColumn + * @param sortDirection * @returns {{loadDateTime: Date, messages}} */ -export function parseMessages(data) { +export function parseMessages(data, sortColumn = null, sortDirection = null) { const loadDatetime = new Date(); //Recursively parse messages to extract useful information - const messages = data.map(message => parseMessage(message, loadDatetime)); + let messages = data.map(message => parseMessage(message, loadDatetime)); //group messages by composition_id const compositions = {}; @@ -396,13 +451,15 @@ export function parseMessages(data) { } // adding not yet enqueued messages - Object.values(compositions).forEach(messages => { - messages.map(message => fillPipe(message, compositions)); + Object.values(compositions).forEach(composition => { + composition.map(message => fillPipe(message, compositions)); }); // assemble compositions - Object.values(compositions).forEach(compositionMessages => { - messages.push(assembleComposition(compositionMessages)); - }); + let assembledCompositions = Object.values(compositions).map(assembleComposition); + // sort the compositions + assembledCompositions = sortByColumn(assembledCompositions, sortColumn, sortDirection); + // insert the compositions with the messages keeping them sorted by column + messages = insertByColumn(messages, assembledCompositions, sortColumn, sortDirection); return { messages: messages, loadDateTime: loadDatetime }; } diff --git a/src/messages/utils.js b/src/messages/utils.js index 9b2923bb..9c5191a8 100644 --- a/src/messages/utils.js +++ b/src/messages/utils.js @@ -37,6 +37,19 @@ const camelCaseToUnderScore = str => { .toLowerCase(); }; +const underScoreToCamelCase = str => { + return str + .split(/_/) + .map((s, index) => { + if (index !== 0) { + return s.charAt(0).toUpperCase() + s.slice(1); + } else { + return s; + } + }) + .join(''); +}; + /** * If item exist in list remove it * otherwise add it. @@ -50,6 +63,7 @@ const toggleItemFromList = (item, list) => { export default { getSortColumnAndDirection, formatMillis, + underScoreToCamelCase, camelCaseToUnderScore, toggleItemFromList }; diff --git a/tests/unit/api.spec.js b/tests/unit/api.spec.js index d9308081..5a98dd5c 100644 --- a/tests/unit/api.spec.js +++ b/tests/unit/api.spec.js @@ -805,6 +805,42 @@ describe('Composition started_time', () => { }); }); +test('Composition enqueued datetime', () => { + expect( + parseMessages([ + { + message_id: 'id0', + enqueued_datetime: '2021-05-01 11:00:00', + options: { + composition_id: 'comp_id', + group_info: { + group_id: 'grp_id' + } + } + }, + { + message_id: 'id1', + enqueued_datetime: '2021-05-01 10:00:00', + options: { + composition_id: 'comp_id', + group_info: { + group_id: 'grp_id' + } + } + }, + { + message_id: 'id2', + options: { + composition_id: 'comp_id', + group_info: { + group_id: 'grp_id' + } + } + } + ]).messages[0].enqueuedDatetime.getTime() + ).toBe(new Date('2021-05-01 10:00:00').getTime()); +}); + test('Composition progress test', () => { expect( parseMessages([ @@ -872,3 +908,72 @@ test('Test group with a pipeline whose last message is a group', () => { } ]); }); + +describe('Composition sorting', () => { + test.each([ + ['ascending', 'asc'], + ['descending', 'desc'] + ])('works when in %s order', (name, direction) => { + const target = [ + { messageId: 'id5', startedDatetime: new Date('2021-05-01 9:00:00') }, + { compositionType: 'group', startedDatetime: new Date('2021-05-01 10:00:00') }, + { messageId: 'id4' }, + { compositionType: 'pipeline' } + ]; + const messages = [ + { + message_id: 'id5', + started_datetime: '2021-05-01 9:00:00' + }, + { + message_id: 'id4' + } + ]; + if (direction === 'desc') { + target.reverse(); + messages.reverse(); + } + expect( + parseMessages( + [ + { + message_id: 'id0', + options: { + composition_id: 'comp0_id', + pipe_target: [ + { + message_id: 'id1', + options: { + composition_id: 'comp0_id' + } + } + ] + } + }, + { + message_id: 'id2', + started_datetime: '2021-05-01 10:00:00', + options: { + composition_id: 'comp1_id', + group_info: { + group_id: 'grp_id' + } + } + }, + { + message_id: 'id3', + started_datetime: '2021-05-01 10:00:00', + options: { + composition_id: 'comp1_id', + group_info: { + group_id: 'grp_id' + } + } + } + ].concat(messages), + 'startedDatetime', + direction + ).messages + ).toMatchObject(target); + }); +});