Skip to content

Add service factories for batched api calls #55

@snsavage

Description

@snsavage

We've recently added service factories for batchedListService and nestedBatchedListService to a client project. These should be moved to src/services/service-factory.ts in this project. To do this, several pieces will be needed.

Types:

export type BatchedListService<TRecord, TQueryParams> = (
    queryParams: TQueryParams,
    property: keyof TQueryParams,
    size: number
) => Promise<ServiceResponse<TRecord>>;
export type NestedBatchedListService<TRecord, TPathParams, TQueryParams> = (
    pathParams: TPathParams,
    queryParams: TQueryParams,
    property: keyof TQueryParams,
    size: number
) => Promise<ServiceResponse<TRecord>>

Public Functions:

const ServiceFactory = {
    batchedList: <TRecord, TQueryParams>(
        recordType: { new (): TRecord },
        baseEndpoint: string
    ): BatchedListService<TRecord, TQueryParams> => {
        return async (
            queryParams: TQueryParams,
            property: keyof TQueryParams,
            size: number
        ) => {
            return _batchList(
                recordType,
                baseEndpoint,
                property,
                size,
                queryParams
            );
        };
    },
    nestedBatchedList: <TRecord, TPathParams, TQueryParams>(
        recordType: { new (): TRecord },
        baseEndpoint: string
    ): NestedBatchedListService<TRecord, TPathParams, TQueryParams> => {
        return async (
            pathParams: TPathParams,
            queryParams: TQueryParams,
            property: keyof TQueryParams,
            size: number
        ) => {
            return _batchList(
                recordType,
                baseEndpoint,
                property,
                size,
                queryParams,
                pathParams
            );
        };
    }
}

Private Function:

const _batchedList = async function<
    TRecord,
    TQueryParams,
    TPathParams = undefined
>(
    recordType: { new (): TRecord },
    baseEndpoint: string,
    property: keyof TQueryParams,
    size: number,
    queryParams: TQueryParams,
    pathParams?: TPathParams
) {
    const values = queryParams[property];
    if (!(values instanceof Array) || CollectionUtils.isEmpty(values)) {
        return ServiceResponseFactory.successfulList<TRecord>();
    }

    const batches = _.chunk(values, size);

    const requests = batches.map((batchValues) => {
        const batchedParams = Object.assign({}, queryParams);
        batchedParams[property] = batchValues as any;

        if (pathParams != null) {
            return AndcultureCodeServiceFactory.nestedList<
                TRecord,
                TPathParams,
                TQueryParams
            >(recordType, baseEndpoint)(pathParams, batchedParams);
        }

        return AndcultureCodeServiceFactory.list<TRecord, TQueryParams>(
            recordType,
            baseEndpoint
        )(batchedParams);
    }) as Promise<ServiceResponse<TRecord>>[];

    const results = await PromiseUtils.toArray(requests);
    return ServiceResponseFactory.successfulList(results, values.length);
};

After the _batchedList private function is added to service-factory.ts the calls to AndcultureCodeServiceFactory.nestedList and AndcultureCodeServiceFactory.list can be swapped out for a single call to the service-factory's private _list function.

Finally, a service-response-factory was added to return a successfulList result. This should also be brought over.

const ServiceResponseFactory = {
    /**
     * Default successful list response
     */
    successfulList<T>(
        resultObjects?: Array<T>,
        rowCount?: number
    ): ServiceResponse<T> {
        return {
            resultObjects: resultObjects ?? [],
            rowCount: rowCount ?? 0,
            status: 200,
        };
    },
};

The implementation in the client project has been tagged with this issue for reference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions