Skip to content

Commit

Permalink
feat: first impl (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
atian25 authored Jul 24, 2020
1 parent 90acb5a commit e18f9dd
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 38 deletions.
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: atian25 # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: atian25 # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
39 changes: 39 additions & 0 deletions .github/workflows/semantic-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Actions Release

on:
push:
branches:
- master

jobs:
Runner:
runs-on: ${{ matrix.os }}

strategy:
matrix:
os: [ubuntu-latest]
node-version: [12.x]

steps:
- name: Checkout Git Source
uses: actions/checkout@v1

- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Install Dependencies
run: |
npm install
- name: Continuous integration
run: |
npm run test
- name: Release NPM Package
run: |
npm run semantic-release
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

Workaround for egg remote config.

It will load remote config at agent's lifecycle, then write to file, then readFileSync at worker's lifecycle.
Because Egg Config Loader is sync, but sometime we need to load remote config.

So, this plugin will load remote config at agent's lifecycle, then write to file, then readFileSync at worker's lifecycle.

## Install

Expand All @@ -37,6 +39,11 @@ exports.remoteConfig = {
```js
// {app_root}/config/config.default.js
exports.remoteConfig = {
async handler(agent) {
// will override app.config
const { data } = await agent.curl('http://remote-url/config', { dataType: 'json', contentType: 'json' });
return data;
}
};
```

Expand Down
33 changes: 33 additions & 0 deletions agent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

const path = require('path');
const fs = require('fs');
const { promisify } = require('util');
const rimraf = require('rimraf');
const writeFile = promisify(fs.writeFile);
const mkdirp = promisify(fs.mkdir);
const del = promisify(rimraf);

module.exports = class AgentBootHook {
constructor(agent) {
this.agent = agent;
this.logger = agent.logger;
this.filePath = path.resolve(agent.config.rundir, agent.config.remoteConfig.savePath);
}

async willReady() {
const { handler } = this.agent.config.remoteConfig;

/* istanbul ignore else */
if (handler) {
this.logger.info(`[RemoteConfig] loading remote config and save to ${this.filePath}`);
const result = await handler(this.agent);
await mkdirp(path.dirname(this.filePath), { recursive: true });
await writeFile(this.filePath, JSON.stringify(result || /* istanbul ignore next */{}, null, 2), 'utf-8');
}
}

async serverDidReady() {
await del(this.filePath);
}
};
26 changes: 26 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
'use strict';

const path = require('path');
const fs = require('fs');
const extend = require('extend2');

module.exports = class AppBootHook {
constructor(app) {
this.app = app;
this.logger = app.logger;
}

configWillLoad() {
const { savePath } = this.app.config.remoteConfig;
const filePath = path.resolve(this.app.config.rundir, savePath);

this.logger.info(`[RemoteConfig] loading remote config from ${filePath}`);

try {
const result = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
extend(true, this.app.config, result);
} catch (err) { /* istanbul ignore next */
this.logger.warn(`[RemoteConfig] load ${filePath} fail: ${err.message}`);
}
}
};
6 changes: 4 additions & 2 deletions config/config.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
/**
* egg-remote-config default config
* @member Config#remoteConfig
* @property {String} SOME_KEY - some description
* @property {Function} handler - remote logic handler
* @property {String} savePath - where to save remote config, relative to rundir
*/
exports.remoteConfig = {

handler: undefined,
savePath: 'remote_config.json',
};
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@
"egg-plugin"
],
"dependencies": {

"extend2": "^1.0.0",
"rimraf": "^3.0.2"
},
"devDependencies": {
"assert-file": "^1.0.0",
"autod": "^3.1.0",
"autod-egg": "^1.1.0",
"egg": "^2.27.0",
"egg-bin": "^4.15.0",
"egg-ci": "^1.15.0",
"egg-mock": "^4.0.0",
"eslint": "^7.5.0",
"eslint-config-egg": "^8.0.1"
"eslint-config-egg": "^8.0.1",
"mz-modules": "^2.1.0"
},
"engines": {
"node": ">=10.0.0"
Expand Down
11 changes: 0 additions & 11 deletions test/fixtures/apps/remote-config-test/app/controller/home.js

This file was deleted.

7 changes: 0 additions & 7 deletions test/fixtures/apps/remote-config-test/app/router.js

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions test/fixtures/apps/remote-config-test/package.json

This file was deleted.

17 changes: 17 additions & 0 deletions test/fixtures/example/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const path = require('path');
const assertFile = require('assert-file');

module.exports = class AppBootHook {
constructor(app) {
this.app = app;
}

configDidLoad() {
const { savePath } = this.app.config.remoteConfig;
const filePath = path.resolve(this.app.config.rundir, savePath);

assertFile(filePath);
}
};
27 changes: 27 additions & 0 deletions test/fixtures/example/config/config.default.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
'use strict';

exports.keys = '123456';

exports.foo = 'foo';

exports.sub = {
a: 'a',
};

exports.remoteConfig = {
async handler(agent) {
// fetch remote config
const { data } = await agent.curl('https://github.com/atian25/egg-remote-config/raw/master/package.json', {
dataType: 'json',
contentType: 'json',
followRedirect: true,
});

return {
foo: data.name,
sub: {
a: 'b',
},
};
},
};
3 changes: 3 additions & 0 deletions test/fixtures/example/config/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

exports.static = false;
4 changes: 4 additions & 0 deletions test/fixtures/example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "example",
"version": "0.0.1"
}
20 changes: 12 additions & 8 deletions test/remote-config.test.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
'use strict';

const mock = require('egg-mock');
const assert = require('assert');
const asserFile = require('assert-file');
const path = require('path');
const { rimraf } = require('mz-modules');

describe('test/remote-config.test.js', () => {
let app;
before(() => {
before(async () => {
app = mock.app({
baseDir: 'apps/remote-config-test',
baseDir: 'example',
});
return app.ready();
await rimraf(path.join(__dirname, 'fixtures/example/run'));
await app.ready();
});

after(() => app.close());
afterEach(mock.restore);

it('should GET /', () => {
return app.httpRequest()
.get('/')
.expect('hi, remoteConfig')
.expect(200);
it('should works', () => {
assert(app.config.foo === 'egg-remote-config');
assert(app.config.sub.a === 'b');
asserFile.fail(path.join(app.config.rundir, 'remote_config.json'));
});
});

0 comments on commit e18f9dd

Please sign in to comment.