Skip to content

Commit

Permalink
[#171435619] get only latest services (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
gunzip authored Feb 25, 2020
1 parent 2172403 commit d4f527d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 15 deletions.
48 changes: 41 additions & 7 deletions GetServices/__tests__/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

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

import { aRetrievedService } from "../../__mocks__/mocks";
import { none, some } from "fp-ts/lib/Option";
import { aRetrievedService, aSeralizedService } from "../../__mocks__/mocks";
import { GetServicesHandler } from "../handler";

describe("GetServices", () => {
it("Should return a query error when a database error occurs", async () => {
const mockServiceModel = {
getCollectionIterator: jest.fn(() => {
return Promise.resolve(left({}));
})
getCollectionIterator: jest.fn(() =>
Promise.resolve({
executeNext: () => Promise.resolve(left(new Error()))
})
)
};

const getServicesHandler = GetServicesHandler(mockServiceModel as any);
Expand All @@ -23,14 +26,33 @@ describe("GetServices", () => {
);

expect(mockServiceModel.getCollectionIterator).toHaveBeenCalledWith();
expect(response.kind).toBe("IResponseSuccessJsonIterator");
expect(response.kind).toBe("IResponseErrorQuery");
});

it("Should return the collection of services from the database", async () => {
const mockServiceModel = {
getCollectionIterator: jest.fn(() =>
Promise.resolve({
executeNext: () => Promise.resolve(right([aRetrievedService]))
executeNext: jest
.fn()
.mockImplementationOnce(() =>
Promise.resolve(
right(
some([
aRetrievedService,
{
...aRetrievedService,
version: 3
},
{
...aRetrievedService,
version: 2
}
])
)
)
)
.mockImplementationOnce(() => Promise.resolve(right(none)))
})
)
};
Expand All @@ -45,6 +67,18 @@ describe("GetServices", () => {
);

expect(mockServiceModel.getCollectionIterator).toHaveBeenCalledWith();
expect(response.kind).toBe("IResponseSuccessJsonIterator");
expect(response.kind).toBe("IResponseSuccessJson");
if (response.kind === "IResponseSuccessJson") {
expect(response.value).toEqual({
items: [
{
...aSeralizedService,
service_metadata: undefined,
version: 3
}
],
page_size: 1
});
}
});
});
49 changes: 41 additions & 8 deletions GetServices/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import { Context } from "@azure/functions";
import * as express from "express";

import { ServiceModel } from "io-functions-commons/dist/src/models/service";
import { mapResultIterator } from "io-functions-commons/dist/src/utils/documentdb";
import {
IFoldableResultIterator,
iteratorToValue,
reduceResultIterator
} from "io-functions-commons/dist/src/utils/documentdb";
import {
AzureApiAuthMiddleware,
IAzureApiAuthorization,
Expand All @@ -23,34 +27,63 @@ import {
wrapRequestHandler
} from "io-functions-commons/dist/src/utils/request_middleware";
import {
IResponseSuccessJsonIterator,
ResponseJsonIterator
IResponseErrorQuery,
ResponseErrorQuery
} from "io-functions-commons/dist/src/utils/response";
import {
checkSourceIpForHandler,
clientIPAndCidrTuple as ipTuple
} from "io-functions-commons/dist/src/utils/source_ip_check";

import { collect, StrMap } from "fp-ts/lib/StrMap";
import {
IResponseSuccessJson,
ResponseSuccessJson
} from "italia-ts-commons/lib/responses";
import { Service as ApiService } from "../generated/definitions/Service";
import { retrievedServiceToApiService } from "../utils/conversions";

type IGetServicesHandlerResult =
| IResponseErrorQuery
| IResponseSuccessJson<{ items: readonly ApiService[]; page_size: number }>;

type IGetServicesHandler = (
context: Context,
auth: IAzureApiAuthorization,
clientIp: ClientIp,
userAttributes: IAzureUserAttributes
) => Promise<IResponseSuccessJsonIterator<ApiService>>;
) => Promise<IGetServicesHandlerResult>;

export function GetServicesHandler(
serviceModel: ServiceModel
): IGetServicesHandler {
return async (_, __, ___, ____) => {
const allRetrievedServicesIterator = await serviceModel.getCollectionIterator();
const allServicesIterator = mapResultIterator(
allRetrievedServicesIterator,
retrievedServiceToApiService
const allServicesIterator: IFoldableResultIterator<
Record<string, ApiService>
> = reduceResultIterator(allRetrievedServicesIterator, (prev, curr) => {
// keep only the latest version
const isNewer =
!prev[curr.serviceId] || curr.version > prev[curr.serviceId].version;
return {
...prev,
...(isNewer
? { [curr.serviceId]: retrievedServiceToApiService(curr) }
: {})
};
});
return (await iteratorToValue(allServicesIterator, {})).fold<
IGetServicesHandlerResult
>(
error => ResponseErrorQuery("Cannot get services", error),
services => {
const items = collect(new StrMap(services), (_____, v) => v);
return ResponseSuccessJson({
items,
page_size: items.length
});
}
);
return ResponseJsonIterator(allServicesIterator);
};
}

Expand Down

0 comments on commit d4f527d

Please sign in to comment.