Skip to content
This repository has been archived by the owner on Dec 23, 2021. It is now read-only.

Commit

Permalink
feat: #25 fast fail
Browse files Browse the repository at this point in the history
  • Loading branch information
Soontao committed Aug 13, 2020
1 parent 40da208 commit c2a2b31
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 2 deletions.
3 changes: 3 additions & 0 deletions src/messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


export const ERROR_BATCH_REQUEST_FAST_FAIL = 'There have been some errors before, so this request failed fast.';
18 changes: 18 additions & 0 deletions src/middlewares/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { NextFunction, Request, Response } from 'express';
import { ODataHttpContext, ODataServer } from '..';
import { BadRequestError } from '../error';
import { createLogger } from '../logger';
import { ERROR_BATCH_REQUEST_FAST_FAIL } from '../messages';
import { ODataRequestMethods } from '../processor';
import { commitTransaction, createTransactionContext, rollbackTransaction } from '../type';

Expand Down Expand Up @@ -48,6 +49,8 @@ export function withODataBatchRequestHandler(server: typeof ODataServer) {
try {
const body: JsonBatchBundle = req.body;

const fastFail = req.get('continue-on-error').trim() == 'false';

// validate inbound payload
const errors = validateRequestBody(body);

Expand All @@ -71,6 +74,21 @@ export function withODataBatchRequestHandler(server: typeof ODataServer) {

try {

// if something wrong before, and fast fail switched on, return fast fail result.
if (anyThingWrong && fastFail) {
groupResults.push({
id: batchRequest.id,
status: 500,
body: {
error: {
code: 500,
message: ERROR_BATCH_REQUEST_FAST_FAIL
}
}
});
continue;
}

const ctx: ODataHttpContext = {
url: batchRequest.url,
method: batchRequest.method,
Expand Down
74 changes: 72 additions & 2 deletions test/type/batch.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { v4 } from 'uuid';
import { BaseODataModel, KeyProperty, ODataEntityType, OptionalProperty } from '../../src';
import { ERROR_BATCH_REQUEST_FAST_FAIL } from '../../src/messages';
import { shutdown } from '../utils/server';
import { createServerAndClient, createTmpConnection } from './utils';

Expand All @@ -24,7 +25,7 @@ describe('Batch Test Suite', () => {

const conn = await createTmpConnection({
name: 'batch_error_test_conn',
entityPrefix: 'batch_unit_test_01',
entityPrefix: 'batch_unit_test_01_',
entities: [B1]
});

Expand Down Expand Up @@ -65,7 +66,7 @@ describe('Batch Test Suite', () => {

const conn = await createTmpConnection({
name: 'batch_transaction_test_conn',
entityPrefix: 'batch_unit_test_02',
entityPrefix: 'batch_unit_test_02_',
entities: [B2]
});

Expand Down Expand Up @@ -101,4 +102,73 @@ describe('Batch Test Suite', () => {

});


it('should support fast failed', async () => {

@ODataEntityType()
class B3 extends BaseODataModel {

@KeyProperty({ generated: 'increment' })
key: number;

@OptionalProperty({ unique: true })
name: string;

@OptionalProperty()
age: number;

}

const testName = v4();
const testName2 = v4();

const conn = await createTmpConnection({
name: 'batch_fast_fail_test_conn',
entityPrefix: 'batch_unit_test_03_',
entities: [B3]
});

const { server, client } = await createServerAndClient(conn, B3);

try {

const es = client.getEntitySet<B3>('B3s');

const requests = [
es.batch().create({ name: testName }),
es.batch().create({ name: testName }),
es.batch().create({ name: testName2 })
];

// with fast fail header
// @ts-ignore
client.commonHeader['continue-on-error'] = 'false';

const responses = await client.execBatchRequestsJson(requests);

expect(responses).toHaveLength(3);

// first request should success
expect(responses[0].status).toBe(201);
// second request should be failed, because the name have the unique constraint
expect(responses[1].status).toBe(500);
// fast fail, even this request could be processed
expect(responses[2].status).toBe(500);
// fast fail error message
expect((await responses[2].json()).error.message).toBe(ERROR_BATCH_REQUEST_FAST_FAIL);


const items = await es.find({ name: testName });
// no items should be created
// whole batch request will be put into 'default' atom group by default (without the parameter)
// and each atom group will share single batch request
// and rollback when any errors occurs
expect(items).toHaveLength(0);

} finally {
await shutdown(server);
}

});

});

0 comments on commit c2a2b31

Please sign in to comment.