Skip to content

Commit 76aa60a

Browse files
authored
Fix registerFunction for placeholders when indexing is on by default (#671)
1 parent 717b0e2 commit 76aa60a

File tree

5 files changed

+117
-18
lines changed

5 files changed

+117
-18
lines changed

src/WorkerChannel.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ export class WorkerChannel {
5959
this.packageJson = {};
6060
}
6161

62+
reset(): void {
63+
// Ideally this resets all app-related data
64+
// That worked is tracked by https://github.com/Azure/azure-functions-nodejs-worker/issues/670
65+
this.workerIndexingLocked = false;
66+
this.isUsingWorkerIndexing = false;
67+
}
68+
6269
/**
6370
* Captured logs or relevant details can use the logs property
6471
* @param requestId gRPC message request id

src/eventHandlers/FunctionEnvironmentReloadHandler.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export class FunctionEnvironmentReloadHandler extends EventHandler<
3131
channel: WorkerChannel,
3232
msg: rpc.IFunctionEnvironmentReloadRequest
3333
): Promise<rpc.IFunctionEnvironmentReloadResponse> {
34+
channel.reset();
35+
3436
const response = this.getDefaultResponse(channel, msg);
3537

3638
// Add environment variables from incoming

test/eventHandlers/FunctionEnvironmentReloadHandler.test.ts

Lines changed: 99 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,30 @@ export namespace Msg {
8080
export const noPackageJsonWarning: rpc.IStreamingMessage = warning(
8181
`Worker failed to load package.json: file does not exist`
8282
);
83+
84+
export function indexingSuccess(functions: rpc.IRpcFunctionMetadata[] = []): rpc.IStreamingMessage {
85+
const response: rpc.IStreamingMessage = {
86+
requestId: 'id',
87+
functionMetadataResponse: {
88+
useDefaultMetadataIndexing: functions.length === 0,
89+
result: {
90+
status: rpc.StatusResult.Status.Success,
91+
},
92+
},
93+
};
94+
if (functions.length > 0) {
95+
response.functionMetadataResponse!.functionMetadataResults = functions;
96+
}
97+
return response;
98+
}
99+
100+
export const receivedIndexingLog: rpc.IStreamingMessage = {
101+
rpcLog: {
102+
message: 'Worker 00000000-0000-0000-0000-000000000000 received FunctionsMetadataRequest',
103+
level: LogLevel.Debug,
104+
logCategory: LogCategory.System,
105+
},
106+
};
83107
}
84108

85109
describe('FunctionEnvironmentReloadHandler', () => {
@@ -92,6 +116,7 @@ describe('FunctionEnvironmentReloadHandler', () => {
92116

93117
afterEach(async () => {
94118
mock.restore();
119+
channel.reset();
95120
await stream.afterEachEventHandlerTest();
96121
});
97122

@@ -305,30 +330,69 @@ describe('FunctionEnvironmentReloadHandler', () => {
305330
expect(channel.packageJson).to.deep.equal(packageJson);
306331
});
307332

333+
const tempDir = 'temp';
334+
const entryPointFilesFullPath = path.join(__dirname, 'entryPointFiles');
335+
async function mockEntryPointFiles(fileName: string): Promise<string> {
336+
const fileSubpath = `entryPointFiles/${fileName}`;
337+
mock({
338+
[tempDir]: {},
339+
[__dirname]: {
340+
'package.json': JSON.stringify({ main: fileSubpath }),
341+
// 'require' and 'mockFs' don't play well together so we need these files in both the mock and real file systems
342+
entryPointFiles: mock.load(entryPointFilesFullPath),
343+
},
344+
});
345+
return fileSubpath;
346+
}
347+
308348
for (const extension of ['.js', '.mjs', '.cjs']) {
309349
it(`Loads entry point (${extension}) in specialization scenario`, async () => {
310-
const cwd = process.cwd();
311-
const tempDir = 'temp';
312-
const fileName = `entryPointFiles/doNothing${extension}`;
313-
const expectedPackageJson = {
314-
main: fileName,
315-
};
316-
mock({
317-
[tempDir]: {},
318-
[__dirname]: {
319-
'package.json': JSON.stringify(expectedPackageJson),
320-
// 'require' and 'mockFs' don't play well together so we need these files in both the mock and real file systems
321-
entryPointFiles: mock.load(path.join(__dirname, 'entryPointFiles')),
350+
const fileSubpath = await mockEntryPointFiles(`doNothing${extension}`);
351+
352+
stream.addTestMessage(WorkerInitMsg.init(path.join(process.cwd(), tempDir)));
353+
await stream.assertCalledWith(
354+
WorkerInitMsg.receivedInitLog,
355+
WorkerInitMsg.warning('Worker failed to load package.json: file does not exist'),
356+
WorkerInitMsg.response
357+
);
358+
359+
stream.addTestMessage({
360+
requestId: 'id',
361+
functionEnvironmentReloadRequest: {
362+
functionAppDirectory: __dirname,
322363
},
323364
});
365+
await stream.assertCalledWith(
366+
Msg.reloadEnvVarsLog(0),
367+
Msg.changingCwdLog(__dirname),
368+
WorkerInitMsg.loadingEntryPoint(fileSubpath),
369+
WorkerInitMsg.loadedEntryPoint(fileSubpath),
370+
Msg.reloadSuccess
371+
);
372+
});
373+
}
324374

325-
stream.addTestMessage(WorkerInitMsg.init(path.join(cwd, tempDir)));
375+
for (const isIndexingOnByDefault of [true, false]) {
376+
it(`registerFunction for placeholders (indexing on by default: ${isIndexingOnByDefault})`, async () => {
377+
const fileName = 'registerFunction.js';
378+
const fileSubpath = await mockEntryPointFiles(fileName);
379+
stream.addTestMessage(WorkerInitMsg.init(path.join(process.cwd(), tempDir)));
326380
await stream.assertCalledWith(
327381
WorkerInitMsg.receivedInitLog,
328382
WorkerInitMsg.warning('Worker failed to load package.json: file does not exist'),
329383
WorkerInitMsg.response
330384
);
331385

386+
if (isIndexingOnByDefault) {
387+
stream.addTestMessage({
388+
requestId: 'id',
389+
functionsMetadataRequest: {
390+
functionAppDirectory: tempDir,
391+
},
392+
});
393+
await stream.assertCalledWith(Msg.receivedIndexingLog, Msg.indexingSuccess());
394+
}
395+
332396
stream.addTestMessage({
333397
requestId: 'id',
334398
functionEnvironmentReloadRequest: {
@@ -338,10 +402,30 @@ describe('FunctionEnvironmentReloadHandler', () => {
338402
await stream.assertCalledWith(
339403
Msg.reloadEnvVarsLog(0),
340404
Msg.changingCwdLog(__dirname),
341-
WorkerInitMsg.loadingEntryPoint(fileName),
342-
WorkerInitMsg.loadedEntryPoint(fileName),
405+
WorkerInitMsg.loadingEntryPoint(fileSubpath),
406+
WorkerInitMsg.loadedEntryPoint(fileSubpath),
343407
Msg.reloadSuccess
344408
);
409+
410+
stream.addTestMessage({
411+
requestId: 'id',
412+
functionsMetadataRequest: {
413+
functionAppDirectory: __dirname,
414+
},
415+
});
416+
await stream.assertCalledWith(
417+
Msg.receivedIndexingLog,
418+
Msg.indexingSuccess([
419+
{
420+
bindings: {},
421+
directory: entryPointFilesFullPath,
422+
functionId: 'testFunc',
423+
name: 'testFunc',
424+
rawBindings: [],
425+
scriptFile: fileName,
426+
},
427+
])
428+
);
345429
});
346430
}
347431
});

test/eventHandlers/TestEventStream.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import { expect } from 'chai';
55
import { EventEmitter } from 'events';
6+
import * as fse from 'fs-extra';
67
import * as path from 'path';
78
import * as sinon from 'sinon';
89
import { AzureFunctionsRpcMessages as rpc } from '../../azure-functions-language-worker-protobuf/src/rpc';
@@ -86,9 +87,12 @@ export class TestEventStream extends EventEmitter implements IEventStream {
8687
}
8788
Object.assign(process.env, this.originalEnv);
8889

89-
// Reset require cache for entryPoint files that depend on timing
90-
const filePath = path.join(__dirname, 'entryPointFiles/longLoad.js');
91-
delete require.cache[require.resolve(filePath)];
90+
// Reset require cache for entryPoint files, otherwise they're only ever loaded once
91+
const entryPointFilesDir = path.join(__dirname, 'entryPointFiles');
92+
const files = await fse.readdir(entryPointFilesDir);
93+
for (const file of files) {
94+
delete require.cache[require.resolve(path.join(entryPointFilesDir, file))];
95+
}
9296

9397
// minor delay so that it's more likely extraneous messages are associated with this test as opposed to leaking into the next test
9498
await new Promise((resolve) => setTimeout(resolve, 20));
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const func = require('@azure/functions-core');
2+
func.registerFunction({ name: 'testFunc', bindings: []}, () => {});

0 commit comments

Comments
 (0)