Skip to content

Commit 6df2614

Browse files
authored
[Cosmos] Adds option for Bulk to continue on error (Azure#14277)
* Adds continue on error bulk option * Formats * Revert test config * Changelog * Adds docs for BulkOptions * Fixes tsdoc escaping
1 parent ffcab01 commit 6df2614

File tree

9 files changed

+59
-6
lines changed

9 files changed

+59
-6
lines changed

sdk/cosmosdb/cosmos/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release History
22

3+
## 3.10.4 (2021-03-12)
4+
5+
- FEATURE: Adds Bulk continueOnError option
6+
37
## 3.10.3 (2021-03-12)
48

59
- BUGFIX: Removes direct dependency on @azure/identity while retaining compatibility.

sdk/cosmosdb/cosmos/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@azure/cosmos",
3-
"version": "3.10.3",
3+
"version": "3.10.4",
44
"description": "Microsoft Azure Cosmos DB Service Node.js SDK for SQL API",
55
"sdk-type": "client",
66
"keywords": [

sdk/cosmosdb/cosmos/review/cosmos.api.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ export const BulkOperationType: {
3232
readonly Replace: "Replace";
3333
};
3434

35+
// @public
36+
export interface BulkOptions {
37+
// (undocumented)
38+
continueOnError?: boolean;
39+
}
40+
3541
// @public
3642
export class ChangeFeedIterator<T> {
3743
fetchNext(): Promise<ChangeFeedResponse<Array<T & Resource>>>;
@@ -65,11 +71,12 @@ export class ChangeFeedResponse<T> {
6571
export class ClientContext {
6672
constructor(cosmosClientOptions: CosmosClientOptions, globalEndpointManager: GlobalEndpointManager);
6773
// (undocumented)
68-
bulk<T>({ body, path, resourceId, partitionKeyRangeId, options }: {
74+
bulk<T>({ body, path, partitionKeyRangeId, resourceId, bulkOptions, options }: {
6975
body: T;
7076
path: string;
7177
partitionKeyRangeId: string;
7278
resourceId: string;
79+
bulkOptions?: BulkOptions;
7380
options?: RequestOptions;
7481
}): Promise<Response<any>>;
7582
// (undocumented)
@@ -352,6 +359,7 @@ export const Constants: {
352359
ALLOW_MULTIPLE_WRITES: string;
353360
IsBatchRequest: string;
354361
IsBatchAtomic: string;
362+
BatchContinueOnError: string;
355363
ForceRefresh: string;
356364
};
357365
WritableLocations: string;
@@ -829,7 +837,7 @@ export class ItemResponse<T extends ItemDefinition> extends ResourceResponse<T &
829837
// @public
830838
export class Items {
831839
constructor(container: Container, clientContext: ClientContext);
832-
bulk(operations: OperationInput[], options?: RequestOptions): Promise<OperationResponse[]>;
840+
bulk(operations: OperationInput[], bulkOptions?: BulkOptions, options?: RequestOptions): Promise<OperationResponse[]>;
833841
changeFeed(partitionKey: string | number | boolean, changeFeedOptions?: ChangeFeedOptions): ChangeFeedIterator<any>;
834842
changeFeed(changeFeedOptions?: ChangeFeedOptions): ChangeFeedIterator<any>;
835843
changeFeed<T>(partitionKey: string | number | boolean, changeFeedOptions?: ChangeFeedOptions): ChangeFeedIterator<T>;

sdk/cosmosdb/cosmos/src/ClientContext.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { RequestContext } from "./request/RequestContext";
2222
import { request as executeRequest } from "./request/RequestHandler";
2323
import { SessionContainer } from "./session/sessionContainer";
2424
import { SessionContext } from "./session/SessionContext";
25+
import { BulkOptions } from "./utils/batch";
2526

2627
/** @hidden */
2728
const log = logger("ClientContext");
@@ -546,14 +547,16 @@ export class ClientContext {
546547
public async bulk<T>({
547548
body,
548549
path,
549-
resourceId,
550550
partitionKeyRangeId,
551+
resourceId,
552+
bulkOptions = {},
551553
options = {}
552554
}: {
553555
body: T;
554556
path: string;
555557
partitionKeyRangeId: string;
556558
resourceId: string;
559+
bulkOptions?: BulkOptions;
557560
options?: RequestOptions;
558561
}): Promise<Response<any>> {
559562
try {
@@ -576,6 +579,8 @@ export class ClientContext {
576579
request.headers[Constants.HttpHeaders.IsBatchRequest] = true;
577580
request.headers[Constants.HttpHeaders.PartitionKeyRangeID] = partitionKeyRangeId;
578581
request.headers[Constants.HttpHeaders.IsBatchAtomic] = false;
582+
request.headers[Constants.HttpHeaders.BatchContinueOnError] =
583+
bulkOptions.continueOnError || false;
579584

580585
this.applySessionToken(request);
581586

sdk/cosmosdb/cosmos/src/client/Item/Items.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
getPartitionKeyToHash,
2121
decorateOperation,
2222
OperationResponse,
23-
OperationInput
23+
OperationInput,
24+
BulkOptions
2425
} from "../../utils/batch";
2526
import { hashV1PartitionKey } from "../../utils/hashing/v1";
2627
import { hashV2PartitionKey } from "../../utils/hashing/v2";
@@ -394,10 +395,12 @@ export class Items {
394395
* ```
395396
*
396397
* @param operations - List of operations. Limit 100
398+
* @param bulkOptions - Optional options object to modify bulk behavior. Pass \{ continueOnError: true \} to continue executing operations when one fails. (Defaults to false) ** NOTE: THIS WILL DEFAULT TO TRUE IN THE 4.0 RELEASE
397399
* @param options - Used for modifying the request.
398400
*/
399401
public async bulk(
400402
operations: OperationInput[],
403+
bulkOptions?: BulkOptions,
401404
options?: RequestOptions
402405
): Promise<OperationResponse[]> {
403406
const {
@@ -443,6 +446,7 @@ export class Items {
443446
partitionKeyRangeId: batch.rangeId,
444447
path,
445448
resourceId: this.container.url,
449+
bulkOptions,
446450
options
447451
});
448452
response.result.forEach((operationResponse: OperationResponse, index: number) => {

sdk/cosmosdb/cosmos/src/common/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export const Constants = {
158158
// Bulk/Batch header
159159
IsBatchRequest: "x-ms-cosmos-is-batch-request",
160160
IsBatchAtomic: "x-ms-cosmos-batch-atomic",
161+
BatchContinueOnError: "x-ms-cosmos-batch-continue-on-error",
161162

162163
// Cache Refresh header
163164
ForceRefresh: "x-ms-force-refresh"

sdk/cosmosdb/cosmos/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export { setAuthorizationTokenHeaderUsingMasterKey } from "./auth";
77
export {
88
Operation,
99
OperationResponse,
10+
BulkOptions,
1011
CreateOperation,
1112
UpsertOperation,
1213
ReplaceOperation,

sdk/cosmosdb/cosmos/src/utils/batch.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ export interface OperationResponse {
2929
resourceBody?: JSONObject;
3030
}
3131

32+
/**
33+
* Options object used to modify bulk execution.
34+
* continueOnError (Default value: false) - Continues bulk execution when an operation fails ** NOTE THIS WILL DEFAULT TO TRUE IN the 4.0 RELEASE
35+
*/
36+
export interface BulkOptions {
37+
continueOnError?: boolean;
38+
}
39+
3240
export function isKeyInRange(min: string, max: string, key: string): boolean {
3341
const isAfterMinInclusive = key.localeCompare(min) >= 0;
3442
const isBeforeMax = key.localeCompare(max) < 0;

sdk/cosmosdb/cosmos/test/public/functional/item.spec.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ describe("bulk item operations", function() {
409409
{
410410
operationType: BulkOperationType.Create,
411411
resourceBody: {
412-
ttl: -10
412+
ttl: -10,
413+
key: "A"
413414
}
414415
},
415416
{
@@ -424,6 +425,27 @@ describe("bulk item operations", function() {
424425
const response = await v2Container.items.bulk(operations);
425426
assert.equal(response[1].statusCode, 424);
426427
});
428+
it("Continues after errors with continueOnError true", async function() {
429+
const operations = [
430+
{
431+
operationType: BulkOperationType.Create,
432+
resourceBody: {
433+
ttl: -10,
434+
key: "A"
435+
}
436+
},
437+
{
438+
operationType: BulkOperationType.Create,
439+
resourceBody: {
440+
key: "A",
441+
licenseType: "B",
442+
id: "o239uroihndsf"
443+
}
444+
}
445+
];
446+
const response = await v2Container.items.bulk(operations, { continueOnError: true });
447+
assert.equal(response[1].statusCode, 201);
448+
});
427449
it("autogenerates IDs for Create operations", async function() {
428450
const operations = [
429451
{

0 commit comments

Comments
 (0)