@autofleet/node-common 2.0.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,35 +18,6 @@ Currently we suppurt:
18
18
  }
19
19
  ```
20
20
 
21
- ## Network
22
- Server 2 Servers communication.
23
-
24
- Implemented:
25
- * Retriving service urls from environment
26
- * Retry - Using https://github.com/softonic/axios-retry
27
- * Caching - TBD
28
- * Syntatic response for fail - TBD
29
- * Circuit Breaking - TBD
30
-
31
- The API is just like [axios](https://github.com/axios/axios) api but the creation of new instance **must** have either `serviceName` or `serviceUrl` in options.
32
-
33
- In case `serviceName` used the constractor will look for an environment varible with the the name `<SERVICE_NAME>_SERVICE_HOST`.
34
-
35
- For Example:
36
- ```
37
- const { Network } = require('@autofleet/node-common');
38
-
39
- n = new Network({ serviceName: 'TEST' });
40
-
41
- n.get('/posts/1');
42
- ```
43
- .env file:
44
- ```
45
- RIDE_SERVICE_HOST=jsonplaceholder.typicode.com
46
- ```
47
-
48
- To learn more [click here](https://blog.risingstack.com/designing-microservices-architecture-for-failure/).
49
-
50
21
  ## Settings
51
22
 
52
23
  ### Adding settings
package/index.js CHANGED
@@ -1,17 +1,7 @@
1
- const Network = require('./network');
2
- const Logger = require('./logger');
3
1
  const Settings = require('./settings');
4
- const client = require('./delorean-client');
5
2
  const Router = require('./router');
6
- const Queue = require('./queue');
7
3
 
8
4
  module.exports = {
9
- Network,
10
- Logger,
11
5
  Settings,
12
- Delorean: {
13
- client,
14
- },
15
6
  Router,
16
- Queue,
17
7
  };
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@autofleet/node-common",
3
- "version": "2.0.1",
3
+ "version": "3.0.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "coverage": "jest --coverage --forceExit --runInBand",
7
7
  "test": "jest --forceExit --runInBand",
8
8
  "test-auto": "jest --watch --runInBand",
9
- "linter": "./node_modules/.bin/eslint ."
9
+ "linter": "eslint ."
10
10
  },
11
11
  "jest": {
12
- "setupTestFrameworkScriptFile": "jest-extended",
13
- "testURL": "http://localhost:8085/"
12
+ "setupFilesAfterEnv": [
13
+ "jest-extended"
14
+ ],
15
+ "testEnvironmentOptions": {
16
+ "url": "http://localhost:8085/"
17
+ }
14
18
  },
15
19
  "repository": {
16
20
  "type": "git",
@@ -23,27 +27,24 @@
23
27
  },
24
28
  "homepage": "https://github.com/Autofleet/node-common",
25
29
  "dependencies": {
26
- "@google-cloud/logging-winston": "^4.1.1",
27
- "axios": "^0.18.0",
30
+ "axios": "^0.28.1",
28
31
  "axios-retry": "^3.1.0",
29
32
  "dotenv": "^5.0.1",
30
- "event-pubsub": "^4.3.0",
31
- "express": "^4.16.2",
32
- "jest": "^22.4.4",
33
- "mock-socket": "^7.1.0",
34
- "node-cache": "^4.2.0",
35
- "node-resque": "^5.4.1",
36
- "portfinder": "^1.0.13",
37
- "qs": "^6.5.2",
38
- "timekeeper": "^2.1.2",
39
- "winston": "^3.0.0",
40
- "ws": "^5.2.1"
33
+ "express": "^4.19.2",
34
+ "node-cache": "^4.2.0"
41
35
  },
42
36
  "devDependencies": {
43
- "eslint": "^4.19.1",
44
- "eslint-config-airbnb": "^16.1.0",
45
- "eslint-plugin-import": "^2.11.0",
37
+ "@autofleet/logger": "^4.0.6",
38
+ "@autofleet/network": "^1.5.1",
39
+ "eslint": "^8.57.0",
40
+ "eslint-config-airbnb-base": "^15.0.0",
41
+ "eslint-plugin-import": "^2.29.1",
42
+ "jest": "^29.7.0",
46
43
  "jest-extended": "^0.7.1",
47
44
  "nock": "^10.0.2"
45
+ },
46
+ "peerDependencies": {
47
+ "@autofleet/logger": ">=4.0.6",
48
+ "@autofleet/network": ">=1.0.0"
48
49
  }
49
50
  }
package/router/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  const { Router } = require('express');
2
- const logger = require('../logger')();
2
+ const { default: Logger } = require('@autofleet/logger');
3
+
4
+ const logger = Logger();
3
5
 
4
6
  const METHODS = [
5
7
  'all',
@@ -12,8 +14,16 @@ const METHODS = [
12
14
  'head',
13
15
  ];
14
16
 
17
+ /**
18
+ * @param {(
19
+ * req: import('express').Request,
20
+ * res: import('express').Response,
21
+ * nextFn: import('express').NextFunction
22
+ * ) => void | PromiseLike<void>} func
23
+ * @returns {import('express').Handler}
24
+ */
15
25
  // eslint-disable-next-line consistent-return
16
- const AfEntryPoint = func => async (req, res, next) => {
26
+ const AfEntryPoint = (func) => async (req, res, next) => {
17
27
  try {
18
28
  await func(req, res, next);
19
29
  } catch (e) {
@@ -25,6 +35,11 @@ const AfEntryPoint = func => async (req, res, next) => {
25
35
  }
26
36
  };
27
37
 
38
+ /**
39
+ * @param {Parameters<typeof Router>[0]} [options]
40
+ * @returns {Router} a monkey-patched express router that
41
+ * will handle async routes (and force a 400 status for codes <500)
42
+ */
28
43
  const AfRouter = (options) => {
29
44
  const myRouter = Router({ mergeParams: true, ...options });
30
45
  METHODS.map((method) => {
package/settings/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  const EventEmitter = require('events');
2
2
  const NodeCache = require('node-cache');
3
- const Network = require('../network');
4
- const Logger = require('../logger');
3
+ const Network = require('@autofleet/network');
4
+ const { default: Logger } = require('@autofleet/logger');
5
5
  // const keysMap = require('./map');
6
6
 
7
7
  const util = require('util');
@@ -14,9 +14,9 @@ require('dotenv').config();
14
14
  const fiveMinutes = 60 * 5;
15
15
  const waitingToNetwork = 'waitingToNetwork';
16
16
 
17
- const findUrl = serviceUrl => serviceUrl ||
18
- (process.env.SETTING_MS_SERVICE_HOST && process.env.SETTING_MS_SERVICE_HOST.length > 0 ? `http://${process.env.SETTING_MS_SERVICE_HOST}/` : undefined) ||
19
- (process.env.NODE_ENV !== 'test' ? 'http://setting-ms.autofleet.io/' : 'http://localhost:9999/');
17
+ const findUrl = (serviceUrl) => serviceUrl
18
+ || (process.env.SETTING_MS_SERVICE_HOST?.length > 0 ? `http://${process.env.SETTING_MS_SERVICE_HOST}/` : undefined)
19
+ || (process.env.NODE_ENV !== 'test' ? 'http://setting-ms.autofleet.io/' : 'http://localhost:9999/');
20
20
 
21
21
  class SettingsManager {
22
22
  static get NEVER_DEFAULT_VALUE() {
@@ -33,6 +33,9 @@ class SettingsManager {
33
33
  return returnValue;
34
34
  }
35
35
 
36
+ /**
37
+ * @param {{ serviceUrl: string; ttl?: number }} param0
38
+ */
36
39
  constructor({ serviceUrl, ttl = fiveMinutes } = {}) {
37
40
  const localServiceUrl = findUrl(serviceUrl);
38
41
 
@@ -72,7 +72,6 @@ describe('Settings', () => {
72
72
  expect(value2).toEqual('value1');
73
73
  });
74
74
 
75
-
76
75
  it('Use only one request for similar keys', async () => {
77
76
  const m = mockSetting('key1EM', 'value1EM');
78
77
  const settings = new Settings({
@@ -119,7 +118,7 @@ describe('Settings', () => {
119
118
  .rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
120
119
  });
121
120
 
122
- it('Throws an error if network error and no default value and success the next time', async (done) => {
121
+ it('Throws an error if network error and no default value and success the next time', (done) => {
123
122
  const settings = new Settings({
124
123
  serviceUrl: `http://${serviceUrl}/`,
125
124
  });
@@ -128,7 +127,6 @@ describe('Settings', () => {
128
127
  expect(f())
129
128
  .rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
130
129
 
131
-
132
130
  setTimeout(async () => {
133
131
  const m = mockSetting('key1', 'value1');
134
132
  expect(await settings.get('key1', settings.NEVER_DEFAULT_VALUE)).toEqual('value1');
@@ -1,52 +0,0 @@
1
- const tk = require('timekeeper');
2
- const WebSocket = require('ws');
3
- const Logger = require('../logger');
4
-
5
- const logger = Logger();
6
-
7
- const createWs = (host, resolve) => {
8
- const ws = new WebSocket(`ws://${host}`);
9
-
10
- ws.on('open', () => {
11
- ws.send(JSON.stringify({ type: 'ping' }));
12
- if (resolve) {
13
- resolve(true);
14
- }
15
- });
16
-
17
- ws.on('error', (error) => {
18
- logger.error('ERROR', error);
19
- });
20
-
21
- ws.on('message', (data) => {
22
- const jsonMsg = JSON.parse(data);
23
-
24
- if (jsonMsg.type === 'freeze') {
25
- logger.info('I know you just sent me back to the future, but I\'m back.I\'m back from the future.', { goingBackTo: jsonMsg.time });
26
- tk.freeze(new Date(jsonMsg.time));
27
- } else if (jsonMsg.type === 'travel') {
28
- tk.travel(jsonMsg.time);
29
- }
30
- });
31
-
32
- ws.on('close', () => {
33
- setTimeout(() => {
34
- if (process.env.TIME_TRAVEL_MS_SERVICE_HOST === host) {
35
- createWs(host, null);
36
- }
37
- }, 500);
38
- });
39
- };
40
-
41
- module.exports = () => new Promise((resolve) => {
42
- const { TIME_TRAVEL_MS_SERVICE_HOST, SHOULD_TIME_TRAVEL } = process.env;
43
- if (TIME_TRAVEL_MS_SERVICE_HOST && SHOULD_TIME_TRAVEL) {
44
- logger.info('If my calculations are correct, when this baby hits 88 miles per hour... you\'re gonna see some serious shit.', {
45
- TIME_TRAVEL_MS_SERVICE_HOST,
46
- });
47
-
48
- createWs(TIME_TRAVEL_MS_SERVICE_HOST, resolve);
49
- } else {
50
- resolve(false);
51
- }
52
- });
@@ -1,105 +0,0 @@
1
- const tk = require('timekeeper');
2
- const deloreanClient = require('./index');
3
- const portfinder = require('portfinder');
4
- const WebSocket = require('ws');
5
-
6
- const { env } = process;
7
-
8
- const createUrl = async () => {
9
- const port = await portfinder.getPortPromise();
10
- return {
11
- url: `127.0.0.1:${port}`,
12
- port,
13
- };
14
- };
15
-
16
- const mockServer = (port, time, type) => {
17
- const wss = new WebSocket.Server({ port });
18
- let gotPing = false;
19
-
20
- wss.on('connection', (ws) => {
21
- ws.on('message', (message) => {
22
- const json = JSON.parse(message);
23
- if (json.type === 'ping') {
24
- gotPing = true;
25
- }
26
- });
27
-
28
- ws.send(JSON.stringify({
29
- type,
30
- time,
31
- }));
32
- });
33
-
34
- return {
35
- close: () => wss.close(),
36
- gotPing: () => gotPing,
37
- };
38
- };
39
-
40
- describe('Logger', () => {
41
- beforeEach(() => {
42
- tk.reset();
43
- env.SHOULD_TIME_TRAVEL = true;
44
- env.TIME_TRAVEL_MS_SERVICE_HOST = '';
45
- });
46
-
47
- afterAll(() => {
48
- env.SHOULD_TIME_TRAVEL = false;
49
- env.TIME_TRAVEL_MS_SERVICE_HOST = '0';
50
- });
51
-
52
- test('Conects to server, sends ping an freeze time', async (done) => {
53
- const { url, port } = await createUrl();
54
- env.TIME_TRAVEL_MS_SERVICE_HOST = url;
55
- const mockedDate = new Date('2013-10-08 12:32:50 +0530').getTime();
56
- const { close, gotPing } = mockServer(port, mockedDate, 'freeze');
57
- await deloreanClient();
58
-
59
- setTimeout(() => {
60
- expect(Date.now()).toEqual(mockedDate);
61
- expect(gotPing()).toBeTruthy();
62
- close();
63
- done();
64
- }, 100);
65
- });
66
-
67
- it('Conects to server, sends ping an freeze time', async (done) => {
68
- const { url, port } = await createUrl();
69
- env.TIME_TRAVEL_MS_SERVICE_HOST = url;
70
- const mockedDate = new Date('2013-10-08 12:32:50 +0530').getTime();
71
- const { close, gotPing } = mockServer(port, mockedDate, 'travel');
72
- await deloreanClient();
73
-
74
- setTimeout(() => {
75
- expect(Date.now()).toBeGreaterThan(mockedDate);
76
- expect(Date.now()).toBeLessThan(new Date('2013-10-08 13:32:50 +0530').getTime());
77
- expect(gotPing()).toBeTruthy();
78
- close();
79
- done();
80
- }, 100);
81
- });
82
-
83
- it('Wont start without TIME_TRAVEL_MS_SERVICE_HOST', async () => {
84
- const { port } = await createUrl();
85
- delete env.TIME_TRAVEL_MS_SERVICE_HOST;
86
- const mockedDate = new Date('2013-10-08 12:32:50 +0530').getTime();
87
- const { close } = mockServer(port, mockedDate, 'travel');
88
- const result = await deloreanClient();
89
-
90
- expect(result).toBeFalsy();
91
- close();
92
- });
93
-
94
- it('Wont start without SHOULD_TIME_TRAVEL', async () => {
95
- const { url, port } = await createUrl();
96
- env.TIME_TRAVEL_MS_SERVICE_HOST = url;
97
- delete env.SHOULD_TIME_TRAVEL;
98
- const mockedDate = new Date('2013-10-08 12:32:50 +0530').getTime();
99
- const { close } = mockServer(port, mockedDate, 'travel');
100
- const result = await deloreanClient();
101
-
102
- expect(result).toBeFalsy();
103
- close();
104
- });
105
- });
package/logger/example.js DELETED
@@ -1,5 +0,0 @@
1
- const logger = require('./index')();
2
-
3
- logger.info('it is working');
4
- logger.error('errors displayed in logs/error.log', { e: new Error('test error') });
5
- logger.debug('debug with object', { a: 5 });
package/logger/index.js DELETED
@@ -1,114 +0,0 @@
1
- const winston = require('winston');
2
-
3
- const { createLogger } = winston;
4
- require('dotenv').config();
5
-
6
- const { env } = process;
7
-
8
- const infoEnvNmaes = [
9
- 'production',
10
- 'staging',
11
- 'test',
12
- ];
13
-
14
- const serializeError = (error) => {
15
- const fields = ['code', 'status', 'statusCode', 'message', 'messageData', 'name', 'stack', 'stackTrace'];
16
- return fields.reduce((v, field) => ({ ...v, [field]: error[field] }), {});
17
- };
18
-
19
- const getLevel = (logLevel) => {
20
- if (logLevel) return logLevel;
21
- if (env.LOG_LEVEL) return env.LOG_LEVEL;
22
- if (infoEnvNmaes.includes(env.NODE_ENV)) return 'info';
23
- if (env.NODE_ENV === 'development') return 'debug';
24
- return 'debug';
25
- };
26
-
27
- const enumerateErrorFormat = winston.format((info) => {
28
- if (info.message instanceof Error) {
29
- info.message = Object.assign({ // eslint-disable-line
30
- message: info.message.message,
31
- stack: info.message.stack,
32
- }, info.message);
33
- }
34
- if (info instanceof Error) {
35
- return Object.assign({
36
- message: info.message,
37
- stack: info.stack,
38
- }, info);
39
- }
40
-
41
- // eslint-disable-next-line array-callback-return
42
- Object.keys(info).map((k) => {
43
- if (info[k] instanceof Error) {
44
- // eslint-disable-next-line no-param-reassign
45
- info[k] = serializeError(info[k]);
46
- }
47
- });
48
-
49
- return info;
50
- });
51
-
52
- const getFormat = () => {
53
- if (env.NODE_ENV === 'production') {
54
- return winston.format.combine(
55
- enumerateErrorFormat(),
56
- winston.format.json(),
57
- );
58
- }
59
-
60
- return winston.format.combine(
61
- enumerateErrorFormat(),
62
- winston.format.splat(),
63
- winston.format.colorize(),
64
- winston.format.simple(),
65
- );
66
- };
67
-
68
- const createLoggerInstance = (level, exceptionHandlers) => {
69
- const transports = [new winston.transports.Console()];
70
-
71
- const logger = createLogger({
72
- level,
73
- format: getFormat(),
74
- transports,
75
- exceptionHandlers,
76
- exitOnError: false,
77
- });
78
-
79
- logger.httpMorganInfo = (options) => {
80
- logger.info(options.url, {
81
- httpRequest: {
82
- status: options.status,
83
- requestUrl: options.url,
84
- requestMethod: options.method,
85
- responseSize: options['content-length'],
86
- latency: {
87
- seconds: parseInt(options['response-time'], 10) / 1000,
88
- nanos: parseInt(options['response-time'], 10) * 1000000,
89
- },
90
- userAgent: options['user-agent'],
91
- },
92
- });
93
- };
94
- if (env.NODE_ENV !== 'production') {
95
- logger.httpMorganInfo = undefined;
96
- }
97
- return logger;
98
- };
99
-
100
- class LoggerInstanceManager {
101
- static getLoggerInstance(logLevel) {
102
- if (!LoggerInstanceManager.instances) {
103
- LoggerInstanceManager.instances = {};
104
- }
105
- const level = getLevel(logLevel);
106
- if (!LoggerInstanceManager.instances[level]) {
107
- LoggerInstanceManager.instances[level] = createLoggerInstance(level);
108
- }
109
- return LoggerInstanceManager.instances[level];
110
- }
111
- }
112
-
113
-
114
- module.exports = LoggerInstanceManager.getLoggerInstance;
@@ -1,54 +0,0 @@
1
- const Logger = require('./index');
2
-
3
- const { env } = process;
4
-
5
- describe('Logger', () => {
6
- it('it`s default level is info', () => {
7
- env.NODE_ENV = '';
8
- const logger = Logger();
9
- expect(logger).toBeDefined();
10
- expect(logger.level).toBe('debug');
11
- });
12
-
13
- it('its default develpment level is debug', () => {
14
- env.NODE_ENV = 'development';
15
- const logger = Logger();
16
- expect(logger.level).toBe('debug');
17
- });
18
-
19
- it('its default test level is info', () => {
20
- env.NODE_ENV = 'test';
21
- const logger = Logger();
22
- expect(logger.level).toBe('info');
23
- });
24
-
25
- it('its default production level is info', () => {
26
- env.NODE_ENV = 'production';
27
- const logger = Logger();
28
- expect(logger.level).toBe('info');
29
- });
30
-
31
- it('its level can be override by LOG_LEVEL env variable', () => {
32
- env.NODE_ENV = 'development';
33
- env.LOG_LEVEL = 'warn';
34
- const logger = Logger();
35
- expect(logger.level).toBe('warn');
36
- });
37
-
38
- it('its level can be override by function variable', () => {
39
- env.NODE_ENV = 'production';
40
- env.LOG_LEVEL = 'warn';
41
- const logger = Logger('silly');
42
- expect(logger.level).toBe('silly');
43
- });
44
-
45
- it('its has functions for each level', () => {
46
- const logger = Logger();
47
- expect(logger.error).toBeFunction();
48
- expect(logger.warn).toBeFunction();
49
- expect(logger.info).toBeFunction();
50
- expect(logger.verbose).toBeFunction();
51
- expect(logger.debug).toBeFunction();
52
- expect(logger.silly).toBeFunction();
53
- });
54
- });
package/network/index.js DELETED
@@ -1,105 +0,0 @@
1
- const axios = require('axios');
2
- const axiosRetry = require('axios-retry');
3
- const Logger = require('../logger');
4
- const qs = require('qs');
5
- const httpAdapter = require('axios/lib/adapters/http');
6
- require('dotenv').config();
7
- /**
8
- * Add support for nock testing
9
- * see s://github.com/axios/axios/issues/305
10
- */
11
- if (process.env.NODE_ENV === 'test') {
12
- axios.defaults.adapter = httpAdapter;
13
- }
14
-
15
- const HTTPMethods = [
16
- 'get',
17
- 'post',
18
- 'delete',
19
- 'head',
20
- 'put',
21
- 'patch',
22
- 'options',
23
- ];
24
-
25
- const defaultSettings = {
26
- timeout: 10000,
27
- headers: { 'X-AF-AUTH': 'ANYONE' },
28
- paramsSerializer: params => qs.stringify(params, { arrayFormat: 'brackets' }),
29
- };
30
-
31
- const getHttpRequestObject = response => ({
32
- status: response.status ? response.status : undefined,
33
- requestUrl: response.config ? response.config.url : undefined,
34
- query: response.config ? response.config.params : undefined,
35
- body: response.config ? response.config.data : undefined,
36
- requestMethod: response.config ? response.config.method.toUpperCase() : undefined,
37
- message: response.message ? response.message.toString() : undefined,
38
- stack: response.stack ? response.stack.toString() : undefined,
39
- });
40
-
41
- module.exports = class Network {
42
- constructor(settings = {}) {
43
- this.settings = Object.assign({}, defaultSettings, settings);
44
- this.createBaseUrl();
45
-
46
- this.axios = axios.create(this.settings);
47
- this.addRetry(settings);
48
- this.buildClassHttpMethods();
49
- this.addLogs();
50
- }
51
-
52
- addRetry(settings) {
53
- axiosRetry(this.axios, {
54
- retries: 0,
55
- retryDelay: axiosRetry.exponentialDelay,
56
- ...settings,
57
- });
58
- }
59
-
60
- addLogs() {
61
- const logger = Logger();
62
- this.axios.interceptors.request.use((request) => {
63
- logger.info(`Start Request: [${request.method.toUpperCase()}] ${request.baseURL} ${request.url}`, {
64
- headers: request.headers,
65
- query: request.params,
66
- body: request.data,
67
- });
68
- return request;
69
- });
70
-
71
- this.axios.interceptors.response.use((response) => {
72
- logger.info(`Finish Request: ${response.config.method.toUpperCase()} ${response.config.url}`, getHttpRequestObject(response));
73
- return response;
74
- }, (error) => {
75
- logger.error('Finish Request with error', { data: error.response ? error.response.data : undefined, ...getHttpRequestObject(error.response || error) });
76
- return error;
77
- });
78
- }
79
-
80
- createBaseUrl() {
81
- if (!this.settings.serviceUrl && !this.settings.serviceName) {
82
- throw new Error('At least one of the settings Missing serviceUrl or serviceName');
83
- }
84
-
85
- const { settings } = this;
86
- if (settings.serviceUrl) {
87
- settings.baseURL = settings.serviceUrl;
88
- } else if (settings.serviceName) {
89
- const envServiceHostName = `${settings.serviceName}_SERVICE_HOST`;
90
- settings.baseURL = `http://${process.env[envServiceHostName]}`;
91
- if (!settings.baseURL) {
92
- throw new Error(`Missing environment variable: ${envServiceHostName}`);
93
- }
94
- }
95
- }
96
-
97
- /**
98
- * Build class methods that wrap axios methods
99
- */
100
- buildClassHttpMethods() {
101
- HTTPMethods.forEach((method) => {
102
- this[method] = (...args) => this.axios[method](...args);
103
- });
104
- }
105
- };
@@ -1,69 +0,0 @@
1
- const nock = require('nock');
2
- const Network = require('./index');
3
-
4
- nock('http://www.google.com')
5
- .get('/resource')
6
- .reply(200, { one: 1 });
7
-
8
-
9
- nock('https://www.apple.com')
10
- .get('/resource')
11
- .reply(200, { two: 2 });
12
-
13
- describe('Network', () => {
14
- it('Making requests by service name from ENV', async () => {
15
- process.env.TEST_SERVICE_HOST = 'www.google.com';
16
- const n = new Network({ serviceName: 'TEST' });
17
- const response = await n.get('/resource');
18
- expect(response).toBeDefined();
19
- expect(response.data).toBeDefined();
20
- expect(response.data.one).toBe(1);
21
- });
22
-
23
- it('Making requests by service name from url', async () => {
24
- const n = new Network({ serviceUrl: 'https://www.apple.com' });
25
- const response = await n.get('/resource');
26
- expect(response).toBeDefined();
27
- expect(response.data).toBeDefined();
28
- expect(response.data.two).toBe(2);
29
- });
30
-
31
- // it('Getting 404', async () => {
32
- // const n = new Network({ serviceUrl: 'https://github.com/' });
33
-
34
- // const action = async () => n.get('/404', {
35
- // query: {
36
- // a: 'b',
37
- // },
38
- // });
39
-
40
- // expect(action()).rejects.toThrow(Error);
41
- // });
42
-
43
- test('Retry 1 time', async () => {
44
- nock('https://www.apple2.com')
45
- .get('/resource')
46
- .once()
47
- .reply(500);
48
-
49
-
50
- nock('https://www.apple2.com')
51
- .get('/resource')
52
- .once()
53
- .reply(200, { two: 2 });
54
-
55
- const n = new Network({ serviceUrl: 'https://www.apple2.com' });
56
- const response = await n.get('/resource', {
57
- query: {
58
- a: 'b',
59
- },
60
- 'axios-retry': {
61
- retries: 1,
62
- },
63
- });
64
-
65
- expect(response).toBeDefined();
66
- expect(response.data).toBeDefined();
67
- expect(response.data.two).toBe(2);
68
- });
69
- });
package/queue/index.js DELETED
@@ -1,107 +0,0 @@
1
- const NodeResque = require('node-resque');
2
- const logger = require('../logger')();
3
-
4
- const redisBaseSettings = {
5
- pkg: 'ioredis',
6
- host: '127.0.0.1',
7
- password: '',
8
- port: 6379,
9
- database: 0,
10
- namespace: 'resque',
11
- };
12
-
13
- class AfQueue {
14
- static redisParams(params) {
15
- return Object.assign({}, redisBaseSettings, params);
16
- }
17
-
18
- constructor() {
19
- this.inited = false;
20
- }
21
-
22
- async exitHandler() {
23
- process.stdin.resume();
24
-
25
- if (this.existing) {
26
- return;
27
- }
28
-
29
- this.existing = true;
30
- logger.info('Will remove AfQueue');
31
-
32
- if (this.worker) {
33
- await this.worker.end();
34
- }
35
-
36
- if (this.queue) {
37
- await this.queue.end();
38
- }
39
-
40
- if (this.scheduler) {
41
- await this.scheduler.end();
42
- }
43
-
44
- process.exit();
45
- }
46
-
47
- async init(connectionDetails, workerSettings, shouldCreateQueue = true) {
48
- if (this.inited) {
49
- throw new Error('AfQueue: Already inited');
50
- }
51
-
52
- const redisConf = Object.assign({}, redisBaseSettings, connectionDetails);
53
- this.inited = true;
54
- const promiseArr = [];
55
- if (shouldCreateQueue) {
56
- await this.startQueue(redisConf);
57
- promiseArr.push(this.startScheduler(redisConf));
58
- }
59
-
60
- if (workerSettings) {
61
- promiseArr.push(this.startWorker(redisConf, workerSettings));
62
- }
63
-
64
- process.on('SIGINT', this.exitHandler.bind(this));
65
- process.on('SIGTERM', this.exitHandler.bind(this));
66
-
67
- return Promise.all(promiseArr);
68
- }
69
-
70
- async getQueue() {
71
- if (!this.queue) {
72
- await this.startQueue();
73
- }
74
- return this.queue;
75
- }
76
-
77
- async startScheduler(connectionDetails) {
78
- this.scheduler = new NodeResque.Scheduler({
79
- connection: AfQueue.redisParams(connectionDetails),
80
- });
81
- await this.scheduler.connect();
82
- this.scheduler.start();
83
- }
84
-
85
- async startQueue(connectionDetails) {
86
- this.queue = new NodeResque.Queue({
87
- connection: AfQueue.redisParams(connectionDetails),
88
- });
89
- await this.queue.connect();
90
- }
91
-
92
- async startWorker(connectionDetails, { queues, jobs }) {
93
- this.worker = new NodeResque.MultiWorker({
94
- connection: AfQueue.redisParams(connectionDetails),
95
- queues,
96
- minTaskProcessors: 1,
97
- maxTaskProcessors: 10,
98
- checkTimeout: 5000,
99
- maxEventLoopDelay: 10,
100
- }, jobs);
101
-
102
- await this.worker.start();
103
- }
104
- }
105
-
106
-
107
- module.exports = new AfQueue();