Skip to content

feat: enable plugin mechanism for async func #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
56ff7ad
✨ feat: enable asycn function plugin
YADROOKIE Jul 20, 2022
10c240f
♻️ refactor enable aysnc function plugin
YADROOKIE Jul 22, 2022
7034730
Merge branch 'OpenFunction:master' into feature/plugin-async
YADROOKIE Jul 22, 2022
be20c3f
Merge branch 'feature/plugin-async' of https://github.com/YADROOKIE/f…
YADROOKIE Jul 22, 2022
c2146ee
🎨 formate code
YADROOKIE Jul 22, 2022
7c1d9e8
🎨 improve aysnc function plugin code
YADROOKIE Jul 23, 2022
c844496
🎨 rename test file gi
YADROOKIE Jul 23, 2022
af1ac61
🎨 improve & formate code
YADROOKIE Jul 25, 2022
4bb5ad6
🎨 format code
YADROOKIE Jul 25, 2022
0d5ceb3
🎨 extract common test data into a separate file for reuse & use Reco…
YADROOKIE Jul 25, 2022
184c2a9
🎨 delete test data
YADROOKIE Jul 25, 2022
eae45d8
🎨 test data in common file
YADROOKIE Jul 27, 2022
a95dad2
🎨 remove annotation
YADROOKIE Jul 27, 2022
b6d1c50
Merge branch 'OpenFunction:master' into feature/plugin-async
YADROOKIE Jul 27, 2022
1c9b4a8
Merge branch 'OpenFunction:master' into feature/plugin-async
YADROOKIE Jul 28, 2022
48946da
Merge branch 'OpenFunction:master' into feature/plugin-async
YADROOKIE Jul 29, 2022
a2f2db7
🎨 improve the codegit
YADROOKIE Aug 3, 2022
fa7c1f5
🎨 imporove plugin loader
YADROOKIE Aug 3, 2022
37a91af
process conflict
YADROOKIE Aug 3, 2022
c1074ad
Merge branch 'OpenFunction:master' into feature/plugin-async
YADROOKIE Aug 3, 2022
75d2422
resolve conflict
YADROOKIE Aug 3, 2022
8403803
add api docs
YADROOKIE Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
OpenFunctionContext,
ContextUtils,
} from './openfunction/function_context';
import {getPlugins} from './plugin';

/**
* Main entrypoint for the functions framework that loads the user's function
Expand All @@ -50,13 +51,16 @@ export const main = async () => {
process.exit(1);
}
const {userFunction, signatureType} = loadedFunction;

if (options.plugin) {
options.plugin = await getPlugins(options.sourceLocation, options.plugin);
}
if (ContextUtils.IsAsyncRuntime(options.context as OpenFunctionContext)) {
options.context!.port = options.port;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this line?

const server = getAysncServer(
userFunction! as OpenFunction,
options.context!
options.context!,
options.plugin
);
await server.start();
} else {
Expand Down
28 changes: 27 additions & 1 deletion src/openfunction/async_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {OpenFunction} from '../functions';

import {OpenFunctionContext, ContextUtils} from './function_context';
import {OpenFunctionRuntime} from './function_runtime';
import {PluginContext, PluginContextRuntime} from '../plugin_context';

export type AsyncFunctionServer = DaprServer;

Expand All @@ -17,13 +18,38 @@ export type AsyncFunctionServer = DaprServer;
*/
export default function (
userFunction: OpenFunction,
context: OpenFunctionContext
context: OpenFunctionContext,
pluginContext?: PluginContext
): AsyncFunctionServer {
const app = new DaprServer('localhost', context.port);
const ctx = OpenFunctionRuntime.ProxyContext(context);

const wrapper = async (data: object) => {
const runtime: PluginContextRuntime | undefined = pluginContext
? {
pluginContext: pluginContext,
data: data,
context: ctx,
}
: undefined;

if (runtime) {
runtime.context = ctx;
runtime.data = data;
for (let i = 0; i < runtime.pluginContext.prePluginFuncs!.length; i++) {
await runtime.pluginContext.prePluginFuncs![i](pluginContext);
data = runtime.data;
}
}
await userFunction(ctx, data);
if (runtime) {
runtime.context = ctx;
runtime.data = data;
for (let i = 0; i < runtime.pluginContext.postPluginFuncs!.length; i++) {
await runtime.pluginContext.postPluginFuncs![i](pluginContext);
data = runtime.data;
}
}
};

// Initialize the server with the user's function.
Expand Down
23 changes: 23 additions & 0 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as minimist from 'minimist';

import {SignatureType, isValidSignatureType} from './types';
import {OpenFunctionContext} from './openfunction/function_context';
import {PluginContext} from './plugin_context';

const debug = Debug('common:options');

Expand Down Expand Up @@ -53,6 +54,10 @@ export interface FrameworkOptions {
* The context to use for the function when serving.
*/
context?: OpenFunctionContext;
/**
* The context to use for the function when serving.
*/
plugin?: PluginContext;
/**
* Whether or not the --help CLI flag was provided.
*/
Expand Down Expand Up @@ -134,7 +139,23 @@ const FunctionContextOption = new ConfigurableOption(
}
}
);
const PluginContextOption = new ConfigurableOption(
'plugin',
'PLUGIN_CONTEXT',
undefined,
x => {
// Try to parse plugin string
debug('ℹ️ Plugin loaded: %s', x);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this line?

try {
const context = JSON.parse(x);
return context as PluginContext;
} catch (e) {
debug('Failed to parse plugin: %s', e);
return undefined;
}
}
);
export const helpText = `Example usage:
functions-framework --target=helloWorld --port=8080
Documentation:
Expand All @@ -158,6 +179,7 @@ export const parseOptions = (
SignatureOption.cliOption,
SourceLocationOption.cliOption,
FunctionContextOption.cliOption,
PluginContextOption.cliOption,
],
});
return {
Expand All @@ -166,6 +188,7 @@ export const parseOptions = (
sourceLocation: SourceLocationOption.parse(argv, envVars),
signatureType: SignatureOption.parse(argv, envVars),
context: FunctionContextOption.parse(argv, envVars),
plugin: PluginContextOption.parse(argv, envVars),
printHelp: cliArgs[2] === '-h' || cliArgs[2] === '--help',
};
};
64 changes: 64 additions & 0 deletions src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as path from 'path';
import * as fs from 'fs';
import {PluginContext} from './plugin_context';

export async function loadPlugins(
codeLocation: string
): Promise<Map<string, Function>> {
const funcMap: Map<string, Function> = new Map();
const param = path.resolve(`${codeLocation}/plugins`);
const plugin_files: Array<string> = [];
const files = fs.readdirSync(param);
files.forEach(f => {
if (f.endsWith('.js')) {
plugin_files.push(path.join(param, f));
}
});
console.log(plugin_files);
plugin_files.forEach(f => {
const pluginModule = require(f);
Object.keys(pluginModule).forEach(key => {
funcMap.set(key, pluginModule[key]);
});
});
return funcMap;
}

export async function getPlugins(
codeLocation: string,
pluginContext: PluginContext
): Promise<PluginContext> {
const funcMapResult: Map<string, Function> = new Map();
const funcMap = await loadPlugins(codeLocation);
pluginContext.pluginMap = funcMap;
pluginContext.prePluginFuncs = [];
pluginContext.postPluginFuncs = [];
pluginContext.prePlugins.forEach(p => {
const func = funcMap.get(p);
if (func) {
funcMapResult.set(p, func);
pluginContext.prePluginFuncs!.push(func);
} else {
console.error('----------------error----------------');
console.error(
`pre-plugin-function[${p}] is not found \nDid you specify the correct target plugin-function to execute?`
);
console.error('-------------------------------------');
}
});
pluginContext.postPlugins.forEach(p => {
const func = funcMap.get(p);
if (func) {
funcMapResult.set(p, func);
pluginContext.postPluginFuncs!.push(func);
} else {
console.error('----------------error----------------');
console.error(
`post-plugin-function[${p}] is not found \nDid you specify the correct target plugin-function to execute?`
);
console.error('-------------------------------------');
}
});

return pluginContext;
}
46 changes: 46 additions & 0 deletions src/plugin_context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {OpenFunctionRuntime} from './functions';
/**
* The OpenFunction's plugin context.
* @public
*/
export interface PluginContext {
/**
* The name of the pre plugins.
*/
prePlugins: Array<string>;
/**
* The name of the pre plugins.
*/
postPlugins: Array<string>;
/**
* The func of the pre plugins.
*/
prePluginFuncs?: Array<Function>;
/**
* The func of the pre plugins.
*/
postPluginFuncs?: Array<Function>;
/**
* The refect between name func.
*/
pluginMap?: Map<string, Function>;
}

/**
* The OpenFunction's plugin context runtime.
* @public
*/
export interface PluginContextRuntime {
/**
* The refect between name func.
*/
pluginContext: PluginContext;
/**
* OpenFunctionRuntime.
*/
context?: OpenFunctionRuntime;
/**
* data.
*/
data?: object;
}