Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
35 changes: 35 additions & 0 deletions app/v4/src/functions/cosmosDBMongoTrigger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { app, InvocationContext } from '@azure/functions';

interface CosmosDBMongoChangeDocument {
operationType?: string;
fullDocument?: {
_id?: string;
testData?: string;
};
documentKey?: {
_id?: string;
};
}

export async function cosmosDBMongoTrigger(
change: CosmosDBMongoChangeDocument,
context: InvocationContext
): Promise<void> {
const document = change.fullDocument;
const documentId = document?._id ?? change.documentKey?._id;
context.log(`cosmosDBMongoTrigger operation "${change.operationType}" for "${documentId}"`);
context.log(`cosmosDBMongoTrigger was triggered by "${document?.testData}"`);
}

(app as any).cosmosDBMongo('cosmosDBMongoTrigger', {
connectionStringSetting: 'CosmosDBMongoConnection',
databaseName: 'e2eTestMongoDB',
collectionName: 'e2eTestMongoCollection',
createIfNotExists: true,
leaseDatabaseName: 'e2eTestMongoDB',
leaseCollectionName: 'e2eTestMongoLeases',
handler: cosmosDBMongoTrigger,
});
30 changes: 30 additions & 0 deletions app/v4/src/functions/httpTriggerCosmosDBMongoInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions';

const cosmosDBMongoInput = (input as any).cosmosDBMongo({
connectionStringSetting: 'CosmosDBMongoConnection',
databaseName: 'e2eTestMongoDB',
collectionName: 'e2eTestMongoCollection',
queryString: '{{"_id":"{Query.id}"}}',
createIfNotExists: true,
});

export async function httpTriggerCosmosDBMongoInput(
_request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
const result = context.extraInputs.get(cosmosDBMongoInput);
const documents = typeof result === 'string' ? JSON.parse(result) : result;
const document = Array.isArray(documents) ? documents[0] : documents;
return { jsonBody: document ?? null };
}

app.http('httpTriggerCosmosDBMongoInput', {
methods: ['GET'],
authLevel: 'anonymous',
extraInputs: [cosmosDBMongoInput],
handler: httpTriggerCosmosDBMongoInput,
});

27 changes: 27 additions & 0 deletions app/v4/src/functions/httpTriggerCosmosDBMongoOutput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions';

const cosmosDBMongoOutput = (output as any).cosmosDBMongo({
connectionStringSetting: 'CosmosDBMongoConnection',
databaseName: 'e2eTestMongoDB',
collectionName: 'e2eTestMongoCollection',
createIfNotExists: true,
});

export async function httpTriggerCosmosDBMongoOutput(
request: HttpRequest,
context: InvocationContext
): Promise<HttpResponseInit> {
const body = await request.json();
context.extraOutputs.set(cosmosDBMongoOutput, body);
return { body: 'done' };
}

app.http('httpTriggerCosmosDBMongoOutput', {
methods: ['POST'],
authLevel: 'anonymous',
extraOutputs: [cosmosDBMongoOutput],
handler: httpTriggerCosmosDBMongoOutput,
});
134 changes: 131 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"mocha": "^10.8.2",
"mocha-junit-reporter": "^2.0.2",
"mocha-multi-reporters": "^1.5.1",
"mongodb": "^6.19.0",
"mssql": "^10.0.2",
"node-fetch": "2.6.7",
"p-retry": "^4.0.0",
Expand Down
8 changes: 8 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export namespace EnvVarNames {
export const storage = 'AzureWebJobsStorage';
export const cosmosDB = 'CosmosDBConnection';
export const cosmosDBMongo = 'CosmosDBMongoConnection';
export const eventHub = 'EventHubConnection';
export const serviceBus = 'ServiceBusConnection';
export const sql = 'SqlConnection';
Expand All @@ -17,6 +18,13 @@ export namespace CosmosDB {
export const partitionKey = 'testPartKey';
}

export namespace CosmosDBMongo {
export const dbName = 'e2eTestMongoDB';
export const collectionName = 'e2eTestMongoCollection';
export const leaseCollectionName = 'e2eTestMongoLeases';
export const cosmosDBMongoTestFileName = 'cosmosDBMongo.test';
}

export namespace EventHub {
export const eventHubOneTriggerAndOutput = 'e2e-test-hub-one-trigger-and-output';
export const eventHubManyTriggerAndOutput = 'e2e-test-hub-many-trigger-and-output';
Expand Down
59 changes: 59 additions & 0 deletions src/cosmosDBMongo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.

import { expect } from 'chai';
import { default as fetch } from 'node-fetch';
import { getFuncUrl } from './constants';
import { isOldConfig, model, waitForOutput } from './global.test';
import { cosmosDBMongoConnectionString } from './utils/connectionStrings';
import { getRandomTestData } from './utils/getRandomTestData';

describe('cosmosDBMongo', () => {
before(function (this: Mocha.Context) {
if (model !== 'v4' || isOldConfig || !cosmosDBMongoConnectionString) {
this.skip();
}
});

type Doc = { _id: string; testData: string };

function getDoc(): Doc {
const data = getRandomTestData();
return { _id: data, testData: data };
}

it('trigger, output, input', async () => {
const document = getDoc();
const outputResponse = await fetch(getFuncUrl('httpTriggerCosmosDBMongoOutput'), {
method: 'POST',
body: JSON.stringify(document),
});
expect(outputResponse.status).to.equal(200);

await waitForOutput(`cosmosDBMongoTrigger was triggered by "${document.testData}"`);

const inputResponse = await fetch(
`${getFuncUrl('httpTriggerCosmosDBMongoInput')}?id=${encodeURIComponent(document._id)}`
);
expect(inputResponse.status).to.equal(200);
const body = await inputResponse.json();
expect(body).to.include(document);
});

it('bulk output triggers once per document', async () => {
const documents: Doc[] = [];
for (let i = 0; i < 3; i++) {
documents.push(getDoc());
}

const outputResponse = await fetch(getFuncUrl('httpTriggerCosmosDBMongoOutput'), {
method: 'POST',
body: JSON.stringify(documents),
});
expect(outputResponse.status).to.equal(200);

for (const document of documents) {
await waitForOutput(`cosmosDBMongoTrigger was triggered by "${document.testData}"`);
}
});
});
Loading
Loading