Skip to content
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

[#152269178] Migrate ComputeVisibleServices to runtime v2 #2

Merged
merged 7 commits into from
Sep 20, 2019
Merged
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
51 changes: 51 additions & 0 deletions CreateService/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* tslint:disable: no-any */
/* tslint:disable: no-big-function */

import * as df from "durable-functions";

import { left, right } from "fp-ts/lib/Either";
import { none } from "fp-ts/lib/Option";

Expand All @@ -10,8 +12,14 @@ import {
aService,
aServicePayload
} from "../../__mocks__/mocks";
import { UpsertServiceEvent } from "../../utils/UpsertServiceEvent";
import { CreateServiceHandler } from "../handler";

beforeEach(() => {
(df.getClient as any).mockClear();
(df as any).mockStartNew.mockClear();
});

describe("CreateServiceHandler", () => {
it("should return a query error if the service fails to be created", async () => {
const mockServiceModel = {
Expand Down Expand Up @@ -72,4 +80,47 @@ describe("CreateServiceHandler", () => {
expect(response.value).toEqual(aSeralizedService);
}
});

it("should start the orchestrator with an appropriate event after the service is created", async () => {
const mockServiceModel = {
create: jest.fn(() => {
return Promise.resolve(right(aRetrievedService));
}),
findOneByServiceId: jest.fn(() => {
return Promise.resolve(right(none));
})
};

const contextMock = {
log: jest.fn()
};

const createServiceHandler = CreateServiceHandler(
undefined as any,
mockServiceModel as any
);

await createServiceHandler(
contextMock as any, // Not used
undefined as any, // Not used
undefined as any, // Not used
undefined as any, // Not used
aServicePayload
);

const upsertServiceEvent = UpsertServiceEvent.encode({
newService: aRetrievedService,
updatedAt: new Date()
});

expect(df.getClient).toHaveBeenCalledTimes(1);

const dfClient = df.getClient(contextMock);
expect(dfClient.startNew).toHaveBeenCalledTimes(1);
expect(dfClient.startNew).toHaveBeenCalledWith(
"UpsertServiceOrchestrator",
undefined,
upsertServiceEvent
);
});
});
5 changes: 5 additions & 0 deletions CreateService/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "orchestrationClient",
"direction": "in",
"name": "starter"
}
],
"scriptFile": "../dist/CreateService/index.js"
Expand Down
43 changes: 35 additions & 8 deletions CreateService/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { Context } from "@azure/functions";

import * as express from "express";

import * as df from "durable-functions";

import { isLeft } from "fp-ts/lib/Either";

import {
IResponseErrorValidation,
IResponseSuccessJson,
ResponseSuccessJson
} from "italia-ts-commons/lib/responses";
Expand Down Expand Up @@ -42,32 +47,54 @@ import {
retrievedServiceToApiService
} from "../utils/conversions";
import { ServicePayloadMiddleware } from "../utils/middlewares/service";
import { UpsertServiceEvent } from "../utils/UpsertServiceEvent";

type ICreateServiceHandler = (
context: Context,
auth: IAzureApiAuthorization,
clientIp: ClientIp,
userAttributes: IAzureUserAttributes,
servicePayload: ApiService
) => Promise<IResponseSuccessJson<ApiService> | IResponseErrorQuery>;
) => Promise<
| IResponseSuccessJson<ApiService>
| IResponseErrorQuery
| IResponseErrorValidation
>;

export function CreateServiceHandler(
_GCTC: CustomTelemetryClientFactory,
serviceModel: ServiceModel
): ICreateServiceHandler {
return async (_, __, ___, ____, servicePayload) => {
return async (context, __, ___, ____, servicePayload) => {
const service = apiServiceToService(servicePayload);
const errorOrCreatedService = await serviceModel.create(
service,
service.serviceId
);
return errorOrCreatedService.fold<
IResponseErrorQuery | IResponseSuccessJson<ApiService>
>(
error => ResponseErrorQuery("CreateServiceHandler error", error),
createdService =>
ResponseSuccessJson(retrievedServiceToApiService(createdService))

if (isLeft(errorOrCreatedService)) {
return ResponseErrorQuery(
"CreateServiceHandler error",
errorOrCreatedService.value
);
}

const createdService = errorOrCreatedService.value;

const upsertServiceEvent = UpsertServiceEvent.encode({
newService: createdService,
updatedAt: new Date()
});

// Start orchestrator
const dfClient = df.getClient(context);
await dfClient.startNew(
"UpsertServiceOrchestrator",
undefined,
upsertServiceEvent
);

return ResponseSuccessJson(retrievedServiceToApiService(createdService));
};
}

Expand Down
58 changes: 58 additions & 0 deletions UpdateService/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* tslint:disable: no-any */
/* tslint:disable: no-big-function */

import * as df from "durable-functions";

import { left, right } from "fp-ts/lib/Either";
import { none, some } from "fp-ts/lib/Option";

Expand All @@ -12,8 +14,14 @@ import {
aSeralizedService,
aServicePayload
} from "../../__mocks__/mocks";
import { UpsertServiceEvent } from "../../utils/UpsertServiceEvent";
import { UpdateServiceHandler } from "../handler";

beforeEach(() => {
(df.getClient as any).mockClear();
(df as any).mockStartNew.mockClear();
});

describe("UpdateServiceHandler", () => {
it("should return a validation error and not update the service if the serviceid in the payload is not equal to the serviceid in the path", async () => {
const aServiceId = "DifferentSubscriptionId" as ServiceId;
Expand Down Expand Up @@ -223,4 +231,54 @@ describe("UpdateServiceHandler", () => {
});
}
});

it("should start the orchestrator with an appropriate event after the service is updated", async () => {
const aDepartmentName = "UpdateDept" as NonEmptyString;
const serviceModelMock = {
findOneByServiceId: jest.fn(() => {
return Promise.resolve(right(some(aRetrievedService)));
}),
update: jest.fn((_, __, f) => {
const updatedService = f(aRetrievedService);
return Promise.resolve(right(some(updatedService)));
})
};

const contextMock = {
log: jest.fn()
};

const updateServiceHandler = UpdateServiceHandler(
undefined as any,
serviceModelMock as any
);

await updateServiceHandler(
contextMock as any, // Not used
undefined as any, // Not used
undefined as any, // Not used
undefined as any, // Not used
aServicePayload.service_id,
{
...aServicePayload,
department_name: aDepartmentName
}
);

const upsertServiceEvent = UpsertServiceEvent.encode({
newService: { ...aRetrievedService, departmentName: aDepartmentName },
oldService: aRetrievedService,
updatedAt: new Date()
});

expect(df.getClient).toHaveBeenCalledTimes(1);

const dfClient = df.getClient(contextMock);
expect(dfClient.startNew).toHaveBeenCalledTimes(1);
expect(dfClient.startNew).toHaveBeenCalledWith(
"UpsertServiceOrchestrator",
undefined,
upsertServiceEvent
);
});
});
5 changes: 5 additions & 0 deletions UpdateService/function.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "orchestrationClient",
"direction": "in",
"name": "starter"
}
],
"scriptFile": "../dist/UpdateService/index.js"
Expand Down
23 changes: 20 additions & 3 deletions UpdateService/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Context } from "@azure/functions";

import * as express from "express";

import * as df from "durable-functions";

import { isLeft } from "fp-ts/lib/Either";
import { isNone } from "fp-ts/lib/Option";

Expand Down Expand Up @@ -53,6 +55,7 @@ import {
} from "../utils/conversions";
import { ServicePayloadMiddleware } from "../utils/middlewares/service";
import { ServiceIdMiddleware } from "../utils/middlewares/serviceid";
import { UpsertServiceEvent } from "../utils/UpsertServiceEvent";

type IUpdateServiceHandler = (
context: Context,
Expand All @@ -74,7 +77,7 @@ export function UpdateServiceHandler(
_GCTC: CustomTelemetryClientFactory,
serviceModel: ServiceModel
): IUpdateServiceHandler {
return async (_, __, ___, ____, serviceId, servicePayload) => {
return async (context, __, ___, ____, serviceId, servicePayload) => {
if (servicePayload.service_id !== serviceId) {
return ResponseErrorValidation(
"Error validating payload",
Expand Down Expand Up @@ -127,9 +130,23 @@ export function UpdateServiceHandler(
return ResponseErrorInternal("Error while updating the existing service");
}

return ResponseSuccessJson(
retrievedServiceToApiService(maybeUpdatedService.value)
const updatedService = maybeUpdatedService.value;

const upsertServiceEvent = UpsertServiceEvent.encode({
newService: updatedService,
oldService: existingService,
updatedAt: new Date()
});

// Start orchestrator
const dfClient = df.getClient(context);
await dfClient.startNew(
"UpsertServiceOrchestrator",
undefined,
upsertServiceEvent
);

return ResponseSuccessJson(retrievedServiceToApiService(updatedService));
};
}

Expand Down
10 changes: 10 additions & 0 deletions UpdateVisibleServicesActivity/function.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
],
"scriptFile": "../dist/UpdateVisibleServicesActivity/index.js"
}
Loading