Skip to content

Commit f808e08

Browse files
committed
refactor: reduced usage of singleton to support parallel calls of fns
1 parent eb6c17f commit f808e08

File tree

10 files changed

+222
-372
lines changed

10 files changed

+222
-372
lines changed

packages/middleware/__tests__/integration/bootstrap/api/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export { success } from "./success";
2+
export { successParalell } from "./successParalell";
23
export { setCookieHeader } from "./setCookieHeader";
34
export { error } from "./error";
45
export { throwAxiosError } from "./throwAxiosError";
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { getLogger } from "../../../../../src";
2+
3+
export const successParalell = (context) => {
4+
const logger = getLogger(context);
5+
logger.info("successParalell");
6+
return Promise.resolve({
7+
status: 200,
8+
message: "ok",
9+
error: false,
10+
});
11+
};

packages/middleware/__tests__/integration/loggerScopes.spec.ts

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,30 +36,47 @@ const testingExtension = {
3636
},
3737
async resueOtherIntegrationMethod(context) {
3838
const logger = getLogger(context);
39-
logger.info("some log");
39+
logger.info("resueOtherIntegrationMethod log");
4040
const int = await context.getApiClient("replicated_integration");
4141
return await int.api[
4242
"replicated-integration-extension"
4343
].orchestrationTest();
4444
},
45+
async paralellOrchestrationTest(context) {
46+
const logger = getLogger(context);
47+
logger.info("resueOtherIntegrationMethod log");
48+
// paralell_replicated_integration
49+
const int = await context.getApiClient("replicated_integration");
50+
const int2 = await context.getApiClient(
51+
"paralell_replicated_integration"
52+
);
53+
// await int.api["replicated-integration-extension"].orchestrationTest();
54+
// await int2.api.successParalell();
55+
return await Promise.all([
56+
int.api["replicated-integration-extension"].orchestrationTest(),
57+
int2.api.successParalell(),
58+
]);
59+
},
4560
},
4661
hooks(req, res, alokai) {
4762
const logger = getLogger(alokai);
4863
logger.info("hooks");
4964
return {
50-
beforeCall({ args }) {
65+
beforeCall({ args, logger }) {
5166
logger.info("bc1");
5267
return args;
5368
},
5469
beforeCreate(a) {
70+
const logger = getLogger(a);
5571
logger.info("bc2");
5672
return a;
5773
},
58-
afterCall({ response }) {
74+
afterCall({ response, logger }) {
5975
logger.info("after1");
6076
return response;
6177
},
6278
afterCreate(a) {
79+
const logger = getLogger(a);
6380
logger.info("after2");
6481
return a;
6582
},
@@ -132,6 +149,19 @@ describe("[Integration] Logger scopes", () => {
132149
];
133150
},
134151
},
152+
paralell_replicated_integration: {
153+
configuration: {},
154+
location: "./__tests__/integration/bootstrap/server",
155+
logger: {
156+
handler: Logger,
157+
},
158+
extensions() {
159+
return [
160+
testingExtension as any,
161+
replicatedIntegrationExtension as any,
162+
];
163+
},
164+
},
135165
},
136166
});
137167
});
@@ -339,6 +369,45 @@ describe("[Integration] Logger scopes", () => {
339369
});
340370
});
341371

372+
test("scope of log from: multiple different integrations called from extension", async () => {
373+
await request(app).post("/test_integration/paralellOrchestrationTest");
374+
375+
expect(Logger.info).toBeCalledWith(expect.any(String), {
376+
context: "middleware",
377+
scope: {
378+
extensionName: "testing-extension",
379+
functionName: "paralellOrchestrationTest",
380+
integrationName: "test_integration",
381+
type: "endpoint",
382+
},
383+
});
384+
expect(Logger.info).toBeCalledWith(expect.any(String), {
385+
context: "middleware",
386+
scope: {
387+
extensionName: "replicated-integration-extension",
388+
functionName: "orchestrationTest",
389+
integrationName: "replicated_integration",
390+
type: "endpoint",
391+
},
392+
});
393+
expect(Logger.info).toBeCalledWith(expect.any(String), {
394+
context: "middleware",
395+
scope: {
396+
functionName: "success",
397+
integrationName: "replicated_integration",
398+
type: "endpoint",
399+
},
400+
});
401+
expect(Logger.info).toBeCalledWith(expect.any(String), {
402+
context: "middleware",
403+
scope: {
404+
functionName: "successParalell",
405+
integrationName: "paralell_replicated_integration",
406+
type: "endpoint",
407+
},
408+
});
409+
});
410+
342411
test("scope of log extendApp", async () => {
343412
await createServer({
344413
logger: {

packages/middleware/src/apiClientFactory/applyContextToApi.ts

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,46 @@ import {
66
BeforeCallParams,
77
MiddlewareContext,
88
} from "../types";
9-
import {
10-
ExtensionEndpointMethodDecorator,
11-
PurgeHookNameMethodDecorator,
12-
MethodDecoratorManager,
13-
MissingScopeMethodDecorator,
14-
OrchiestratedMethodDecorator,
15-
ScopeTypeMethodDecorator,
16-
} from "./methodDecorator";
9+
import { createExtendQuery } from "./createExtendQuery";
10+
import { markExtensionNameHelpers } from "./markExtensionNameHelpers";
11+
import { getLogger, injectMetadata } from "../logger";
1712

1813
const nopBefore = <ARGS>({ args }: BeforeCallParams<any, ARGS>): ARGS => args;
1914
const nopAfter = <RESPONSE>({
2015
response,
2116
}: AfterCallParams<any, any, RESPONSE>) => response;
2217

23-
const checkMetadataScope = <CONTEXT extends MiddlewareContext>(
24-
context: CONTEXT
25-
) => Boolean(context.res.locals?.alokai?.metadata?.scope);
18+
/**
19+
* @returns Instance of Logger with injected metadata of currently called handler and it's integration
20+
*/
21+
function injectHandlerMetadata<CONTEXT extends MiddlewareContext>(
22+
context: CONTEXT,
23+
fn: Function,
24+
callName: string
25+
) {
26+
return injectMetadata(getLogger(context), (metadata) => {
27+
const newMetadata = {
28+
...metadata,
29+
scope: {
30+
...metadata?.scope,
31+
type: "endpoint" as const,
32+
/**
33+
* The following lines ensure proper functionality in case of orchestration.
34+
* In this scenario, there are multiple self-invocations of the function template we see here.
35+
* Adding the currently known functionName and integrationName prevents scope confusion
36+
* between different recurrent synchronous and parallel invocations (e.g., multiple orchestrated methods
37+
* executed with Promise.all).
38+
*/
39+
functionName: callName,
40+
integrationName: context.integrationTag,
41+
},
42+
};
43+
if (markExtensionNameHelpers.has(fn)) {
44+
newMetadata.scope.extensionName = markExtensionNameHelpers.get(fn);
45+
}
46+
return newMetadata;
47+
});
48+
}
2649

2750
/**
2851
* Wraps api methods with context and hooks triggers
@@ -44,27 +67,28 @@ const applyContextToApi = <
4467
(prev, [callName, fn]) => ({
4568
...prev,
4669
[callName]: async (...args: Parameters<typeof fn>) => {
47-
const methodDecoratorManager = new MethodDecoratorManager(
48-
context,
49-
hooks,
70+
const transformedArgs = await hooks.before({
5071
callName,
51-
fn
72+
args,
73+
});
74+
const apiClientContext = {
75+
...context,
76+
extendQuery: createExtendQuery(context),
77+
};
78+
const response = await fn(
79+
{
80+
...apiClientContext,
81+
logger: injectHandlerMetadata(context, fn, callName),
82+
},
83+
...transformedArgs
5284
);
85+
const transformedResponse = await hooks.after({
86+
callName,
87+
args,
88+
response,
89+
});
5390

54-
const hasMetadataScope = checkMetadataScope(context);
55-
const decoratorsToAdd = hasMetadataScope
56-
? [
57-
new ScopeTypeMethodDecorator(context),
58-
new PurgeHookNameMethodDecorator(context),
59-
new ExtensionEndpointMethodDecorator(context, fn),
60-
new OrchiestratedMethodDecorator(context, callName, fn),
61-
]
62-
: [new MissingScopeMethodDecorator(context, callName, fn.name)];
63-
methodDecoratorManager.addDecorator(...decoratorsToAdd);
64-
65-
const method = methodDecoratorManager.prepare<typeof args>();
66-
67-
return await method(args);
91+
return transformedResponse;
6892
},
6993
}),
7094
{} as any

0 commit comments

Comments
 (0)