Skip to content

Commit

Permalink
update from master
Browse files Browse the repository at this point in the history
  • Loading branch information
e11sy committed Dec 25, 2024
2 parents 027d807 + 1322621 commit 96ad5e6
Show file tree
Hide file tree
Showing 30 changed files with 2,719 additions and 31 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ ecosystem.config.js
node_modules
/workers/release/tests/mock
/workers/migrations
/workers/sentry/playground
.github
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ module.exports = {
jest: true,
},
extends: ['codex', 'codex/ts'],
ignorePatterns: [
'package.json',
'tsconfig.json',
'dist',
],
rules: {
'@typescript-eslint/no-unused-expressions': 'error',
'@typescript-eslint/no-var-requires': 'off',
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ on: [push]
jobs:
lint:
name: Unit testing
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 16.x
- run: yarn install
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ RUN yarn install
COPY runner.ts tsconfig.json ./
COPY lib/ ./lib/

RUN yarn tsc
RUN yarn build
2 changes: 1 addition & 1 deletion jest-mongodb-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
dbName: 'hawk',
},
binary: {
version: '4.4.6',
version: '6.0.2',
skipMD5: true,
},
autoStart: false,
Expand Down
4 changes: 4 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ const mockedAmqpConnection = {
const mockedConnect = amqp.connect;

mockedConnect.mockResolvedValue(Promise.resolve(mockedAmqpConnection));

module.exports = {
mockedAmqpChannel,
};
63 changes: 59 additions & 4 deletions lib/logger.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,75 @@
import { createLogger as createWinstonLogger, format, transports, Logger } from 'winston';

/**
* Extend Logger interface with custom "json" method
*/
interface CustomLogger extends Logger {
/**
* Method for logging JSON objects
*
* @param obj - JSON object to log
*
* @example
* logger.json({ foo: 'bar' });
*/
json: (obj: unknown) => void;
}

/**
* Creates new logger instance
*/
export default function createLogger(): Logger {
return createWinstonLogger({
export default function createLogger(): CustomLogger {
const logger = createWinstonLogger({
level: process.env.LOG_LEVEL || 'info',
transports: [
new transports.Console({
format: format.combine(
format.errors({ stack: true }),
format.timestamp(),
format.colorize(),
format.simple(),
format.printf((msg) => `${msg.timestamp} - ${msg.level}: ${msg.message}`)
format.printf(({ level, message, timestamp, stack }) => {
if (stack) {
return `${timestamp} ${level}: ${message} - ${stack}`;
}

return `${timestamp} ${level}: ${message}`;
})
),
}),
],
});
}) as CustomLogger;

/**
* Method for logging JSON objects
*
* @param obj - JSON object to log
*
* @example
* logger.json({ foo: 'bar' });
*/
logger.json = function (obj: unknown): void {
const indent = 2;

/**
* Convert object to formatted string with proper indentation
*/
const formattedJson = typeof obj === 'string'
? JSON.stringify(JSON.parse(obj), null, indent)
: JSON.stringify(obj, null, indent);

/**
* Split the JSON string into lines
*/
const lines = formattedJson.split('\n');

/**
* Log each line to preserve formatting and colors
*/
lines.forEach(line => {
this.info(line);
});
};

return logger;
}
28 changes: 26 additions & 2 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,33 @@ module.exports.deepMerge = deepMerge;
* @returns {object}
*/
function deepDiff(source, target) {
if (typeOf(target) === 'array') {
const sourceType = typeOf(source);
const targetType = typeOf(target);

/**
* If we'll compare NOTHING with SOMETHING, the diff will be SOMETHING
*/
if (source === undefined) {
return target;
}

/**
* If we'll compare SOMETHING with NOTHING, the diff will be NOTHING
*/
if (targetType === undefined) {
return undefined;
}

/**
* We CAN'T compare apples with dogs
*/
if (sourceType !== targetType) {
return undefined;
}

if (targetType === 'array') {
return arrayDiff(source, target);
} else if (typeOf(target) === 'object') {
} else if (targetType === 'object') {
return objectDiff(source, target);
} else if (source !== target) {
return target;
Expand Down
135 changes: 135 additions & 0 deletions lib/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,35 @@ describe('Utils', () => {
files: [ { line: 1 }, { line: 2 }, { line: 3 } ],
},
},

/**
* The first - an empty array
* The second - array with the children non-empty array
*/
{
sourceObject: {
prop: [],
},
targetObject: {
prop: [ [ 'i am not empty' ] ],
},
expectedDiff: {
prop: [ [ 'i am not empty' ] ],
},
expectedMerge: {
prop: [ [ 'i am not empty' ] ],
},
},

/**
* Trying to compare two things of different type
*/
{
sourceObject: [],
targetObject: {},
expectedDiff: undefined,
expectedMerge: {},
},
];

test('should return right object diff', () => {
Expand All @@ -135,4 +164,110 @@ describe('Utils', () => {
expect(merge).toEqual(testCase.expectedMerge);
});
});

/**
* This test is a temporary solution to handle case with invalid events format sent by the PHP catcher
*
* The problem: the PHP catcher sends some data via incompatible format under invalid names and types.
* Those fields leads to the issues with diff calculation since fields could have different structure and types.
*
* The solution: deepDiff will return undefined in case of comparison of things with different types
*
* Original issue:
* https://github.com/codex-team/hawk.workers/issues/312
*
* PHP Catcher issue:
* https://github.com/codex-team/hawk.php/issues/39
*/
test('should not throw error comparing events with incompatible format', () => {
const originalStackTrace = [
{
function: 'postAddComment',
class: 'Components\\Comments\\Comments',
object: {},
type: '->',
args: [
286131,
{},
],
},
];

const repetitionStackTrace = [
{
file: '/var/www/osnova/vendor/php-di/invoker/src/Invoker.php',
line: 74,
function: 'call_user_func_array',
args: [
[
{},
'sendWebhooksJob',
],
[
[
{
id: 6697,
token: '539506',
event: 'new_comment',
url: 'https://callback.angry.space/vc_callback?date=2020&code=lMzBjOWZh@DADAD@jFlZmUy',
filter: '[]',
data: '[]',
removed: false,
},
],
{
type: 'new_comment',
data: {
id: 3206086,
url: 'https://somesite.io/trade/286961',
text: 'Это только со стороны так вроде долго, а если смотреть изнутри, то пока там освободиться купьер, пока найдут товар пока разберуться куда везти может и 4 часа пройти.',
media: [],
date: '2021-08-27T18:08:30+03:00',
creator: {
id: 27823,
avatar: 'https://s3.somesite.io/8ddee2e8-28e4-7863-425e-dd9b06deae5d/',
name: 'John S.',
url: 'https://somesite.io/u/27823-john-s',
},
content: {
id: 286961,
title: 'Wildberries запустил доставку товаров за 2 часа в Петербурге',
url: 'https://somesite.io/trade/286961',
owner: {
id: 199122,
name: 'Торговля',
avatar: 'https://leonardo.osnova.io/d8fbb348-a8fd-641c-55dd-6a404055b457/',
url: 'https://somesite.io/trade',
},
},
replyTo: {
id: 3205883,
url: 'https://somesite.io/trade/286961',
text: 'Никто не пошутил, тогда это сделаю я!\n\n- 2.. часа!!1',
media: [],
creator: {
id: 877711,
avatar: 'https://leonardo.osnova.io/476a4e2c-8045-5b77-8a37-f6b1eb58bf93/',
name: 'Вадим Осадчий',
url: 'https://somesite.io/u/877711-john-doe',
},
},
},
},
],
],
},
];

const diff = utils.deepDiff(originalStackTrace, repetitionStackTrace);

expect(diff).toEqual([
{
file: '/var/www/osnova/vendor/php-di/invoker/src/Invoker.php',
line: 74,
function: 'call_user_func_array',
args: [undefined, undefined],
},
]);
});
});
10 changes: 10 additions & 0 deletions lib/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ export abstract class Worker {
}
}

/**
* Mute or unmute logger
* Used to mute logger in tests where we are expecting errors
*
* @param state - true to mute, false to unmute
*/
public muteLogger(state: boolean): void {
this.logger.level = state ? 'none' : (process.env.LOG_LEVEL || 'info');
}

/**
* Create cache controller instance
*/
Expand Down
12 changes: 12 additions & 0 deletions lib/workerNames.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@
const fs = require('fs');
const path = require('path');
const workersDir = fs.readdirSync(path.resolve(__dirname, '..', 'workers'), { withFileTypes: true });

/**
* @typedef {string} WorkerNameKey
*/

/**
* @typedef {string} WorkerName
*/

/**
* @type {Record<WorkerNameKey, WorkerName>}
*/
const workers = {};

workersDir.forEach(file => {
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"workers/*"
],
"scripts": {
"build": "tsc",
"worker": "ts-node -T ./runner.ts",
"migration-add": "migrate-mongo create",
"migrate:up": "migrate-mongo up",
Expand All @@ -19,6 +20,7 @@
"test:db": "jest lib/db/",
"test:cache": "jest lib/cache",
"test:default": "jest workers/default",
"test:sentry": "jest workers/sentry --config workers/sentry/jest.config.js",
"test:javascript": "jest workers/javascript",
"test:release": "jest workers/release",
"test:slack": "jest workers/slack",
Expand All @@ -28,6 +30,7 @@
"test:notifier": "jest workers/notifier",
"test:clear": "jest --clearCache",
"run-default": "yarn worker hawk-worker-default",
"run-sentry": "yarn worker hawk-worker-sentry",
"run-js": "yarn worker hawk-worker-javascript",
"run-slack": "yarn worker hawk-worker-slack",
"run-grouper": "yarn worker hawk-worker-grouper",
Expand Down
Loading

0 comments on commit 96ad5e6

Please sign in to comment.