triangle-utils 1.4.106 → 1.4.108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -58,7 +58,9 @@ export declare class UtilsDynamoDB {
58
58
  remove(table_name: string, key: Record<string, any>, attributes: string[]): Promise<void>;
59
59
  create(table_name: string, key: Record<string, any>, attributes?: Record<string, any>): Promise<void>;
60
60
  delete(table_name: string, key: Record<string, any>): Promise<void>;
61
- batch_put(table_name: string, items: Record<string, any>[]): Promise<void>;
61
+ batch_put(table_name: string, items: Record<string, any>[], options?: {
62
+ is_verbose?: boolean;
63
+ }): Promise<void>;
62
64
  batch_delete(table_name: string, keys: Record<string, any>[]): Promise<void>;
63
65
  duplicate_attribute(table_name: string, attribute_name: string, new_attribute_name: string): Promise<void>;
64
66
  remove_attribute(table_name: string, attribute_name: string): Promise<undefined>;
@@ -1,4 +1,6 @@
1
+ import { ThrottlingException } from "@aws-sdk/client-bedrock-runtime";
1
2
  import { DynamoDB } from "@aws-sdk/client-dynamodb";
3
+ import { UtilsMisc } from "./UtilsMisc.js";
2
4
  function convert_output(dynamodb_output) {
3
5
  if (dynamodb_output.S !== undefined) {
4
6
  return dynamodb_output.S;
@@ -498,7 +500,8 @@ export class UtilsDynamoDB {
498
500
  Key: converted_key
499
501
  });
500
502
  }
501
- async batch_put(table_name, items) {
503
+ async batch_put(table_name, items, options = {}) {
504
+ const is_verbose = options.is_verbose !== undefined ? options.is_verbose : false;
502
505
  const dynamodb_items = items.map(item => convert_input(item)?.M)
503
506
  .filter(dynamodb_item => dynamodb_item !== undefined);
504
507
  for (let i = 0; i < dynamodb_items.length; i += 25) {
@@ -508,12 +511,24 @@ export class UtilsDynamoDB {
508
511
  }
509
512
  }));
510
513
  while (next_dynamodb_requests.length > 0) {
511
- const response = await this.dynamodb.batchWriteItem({
512
- RequestItems: {
513
- [table_name]: next_dynamodb_requests
514
+ try {
515
+ const response = await this.dynamodb.batchWriteItem({
516
+ RequestItems: {
517
+ [table_name]: next_dynamodb_requests
518
+ }
519
+ });
520
+ next_dynamodb_requests = response.UnprocessedItems?.[table_name] || [];
521
+ }
522
+ catch (error) {
523
+ if (error instanceof ThrottlingException) {
524
+ if (is_verbose) {
525
+ console.log("Throttled.");
526
+ }
527
+ await UtilsMisc.wait(1000);
528
+ continue;
514
529
  }
515
- });
516
- next_dynamodb_requests = response.UnprocessedItems?.[table_name] || [];
530
+ throw error;
531
+ }
517
532
  }
518
533
  }
519
534
  }
@@ -7,7 +7,15 @@ export declare class UtilsMisc {
7
7
  readonly config: GlobalConfig;
8
8
  constructor(config: GlobalConfig);
9
9
  safe_run<T>(f: () => Promise<T>): Promise<T | undefined>;
10
- iterate<T, U>(inputs: T[], f: (input: T, iterator_id: number, index: number) => Promise<U>, num_iterators?: number, print_option?: number | boolean): Promise<(U | undefined)[]>;
10
+ iterate<T, U>(inputs: T[], f: (input: T, iterator_id: number, index: number) => Promise<U>, num_iterators?: number, options?: {
11
+ num_iterators?: number;
12
+ verbosity?: number | boolean;
13
+ }): Promise<(U | undefined)[]>;
14
+ batch_iterate<T, U>(inputs: T[], f: (inputs: T[], iterator_id: number, index: number) => Promise<U>, options: {
15
+ batch_size?: number;
16
+ num_iterators?: number;
17
+ verbosity?: number | boolean;
18
+ }): Promise<(U | undefined)[]>;
11
19
  static wait(duration: number): Promise<unknown>;
12
20
  static get_current_time(): string;
13
21
  static get_current_milliseconds(): number;
@@ -21,8 +21,8 @@ export class UtilsMisc {
21
21
  }
22
22
  return undefined;
23
23
  }
24
- async iterate(inputs, f, num_iterators = 1, print_option) {
25
- const print_freq = typeof print_option === "boolean" ? (print_option === true ? 1 : 0) : print_option;
24
+ async iterate(inputs, f, num_iterators = 1, options = {}) {
25
+ const verbosity = typeof options.verbosity === "boolean" ? (options.verbosity === true ? 1 : 0) : (options.verbosity || 0);
26
26
  let index = 0;
27
27
  let iterators = [];
28
28
  const outputs = new Array(inputs.length).fill(undefined);
@@ -31,7 +31,7 @@ export class UtilsMisc {
31
31
  while (index < inputs.length) {
32
32
  const local_index = index;
33
33
  index += 1;
34
- if (print_freq !== undefined && (local_index % print_freq === 0)) {
34
+ if (verbosity !== undefined && (local_index % verbosity === 0)) {
35
35
  console.log(iterator_id + ":" + local_index + "/" + inputs.length);
36
36
  }
37
37
  const output = await this.safe_run(() => f(inputs[local_index], iterator_id, local_index));
@@ -42,6 +42,29 @@ export class UtilsMisc {
42
42
  await Promise.all(iterators);
43
43
  return outputs;
44
44
  }
45
+ async batch_iterate(inputs, f, options) {
46
+ const batch_size = options.batch_size || 1;
47
+ const num_iterators = options.num_iterators || 0;
48
+ const verbosity = typeof options.verbosity === "boolean" ? (options.verbosity === true ? 1 : 0) : (options.verbosity || 0);
49
+ let index = 0;
50
+ let iterators = [];
51
+ const outputs = new Array(inputs.length).fill(undefined);
52
+ for (let iterator_id = 0; iterator_id < num_iterators; iterator_id++) {
53
+ iterators.push((async () => {
54
+ while (index < inputs.length) {
55
+ const local_index = index;
56
+ index += batch_size;
57
+ if (verbosity !== undefined && (local_index % verbosity === 0)) {
58
+ console.log(iterator_id + ":" + local_index + "/" + inputs.length);
59
+ }
60
+ const output = await this.safe_run(() => f(inputs.slice(local_index, local_index + batch_size), iterator_id, local_index));
61
+ outputs[local_index] = output;
62
+ }
63
+ })());
64
+ }
65
+ await Promise.all(iterators);
66
+ return outputs;
67
+ }
45
68
  static async wait(duration) {
46
69
  return new Promise(resolve => setTimeout(resolve, duration));
47
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triangle-utils",
3
- "version": "1.4.106",
3
+ "version": "1.4.108",
4
4
  "main": "dist/src/index.js",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "directories": {
@@ -1,4 +1,6 @@
1
+ import { ThrottlingException } from "@aws-sdk/client-bedrock-runtime"
1
2
  import { AttributeValue, DynamoDB, QueryCommandInput, QueryCommandOutput, ScanCommandInput, ScanCommandOutput, UpdateItemCommandInput, WriteRequest } from "@aws-sdk/client-dynamodb"
3
+ import { UtilsMisc } from "./UtilsMisc"
2
4
 
3
5
  function convert_output(dynamodb_output : AttributeValue) : string | boolean | number | any[] | Set<any> | Record<string, any> | undefined {
4
6
  if (dynamodb_output.S !== undefined) {
@@ -615,8 +617,12 @@ export class UtilsDynamoDB {
615
617
 
616
618
  async batch_put(
617
619
  table_name : string,
618
- items : Record<string, any>[]
620
+ items : Record<string, any>[],
621
+ options : {
622
+ is_verbose? : boolean
623
+ } = {}
619
624
  ) : Promise<void> {
625
+ const is_verbose = options.is_verbose !== undefined ? options.is_verbose : false
620
626
  const dynamodb_items = items.map(item => convert_input(item)?.M)
621
627
  .filter(dynamodb_item => dynamodb_item !== undefined)
622
628
 
@@ -627,12 +633,23 @@ export class UtilsDynamoDB {
627
633
  }
628
634
  }))
629
635
  while (next_dynamodb_requests.length > 0) {
630
- const response = await this.dynamodb.batchWriteItem({
631
- RequestItems : {
632
- [table_name] : next_dynamodb_requests
636
+ try {
637
+ const response = await this.dynamodb.batchWriteItem({
638
+ RequestItems : {
639
+ [table_name] : next_dynamodb_requests
640
+ }
641
+ })
642
+ next_dynamodb_requests = response.UnprocessedItems?.[table_name] || []
643
+ } catch (error : any) {
644
+ if (error instanceof ThrottlingException) {
645
+ if (is_verbose) {
646
+ console.log("Throttled.")
647
+ }
648
+ await UtilsMisc.wait(1000)
649
+ continue
633
650
  }
634
- })
635
- next_dynamodb_requests = response.UnprocessedItems?.[table_name] || []
651
+ throw error
652
+ }
636
653
  }
637
654
  }
638
655
  }
package/src/UtilsMisc.ts CHANGED
@@ -31,8 +31,8 @@ export class UtilsMisc {
31
31
  return undefined
32
32
  }
33
33
 
34
- async iterate<T, U>(inputs : T[], f : (input : T, iterator_id : number, index : number) => Promise<U>, num_iterators : number = 1, print_option? : number | boolean) {
35
- const print_freq : number | undefined = typeof print_option === "boolean" ? (print_option === true ? 1 : 0) : print_option
34
+ async iterate<T, U>(inputs : T[], f : (input : T, iterator_id : number, index : number) => Promise<U>, num_iterators : number = 1, options : { num_iterators? : number, verbosity? : number | boolean } = {}) {
35
+ const verbosity : number = typeof options.verbosity === "boolean" ? (options.verbosity === true ? 1 : 0) : (options.verbosity || 0)
36
36
  let index = 0
37
37
  let iterators = []
38
38
  const outputs : (U | undefined)[] = new Array(inputs.length).fill(undefined)
@@ -41,7 +41,7 @@ export class UtilsMisc {
41
41
  while (index < inputs.length) {
42
42
  const local_index = index
43
43
  index += 1
44
- if (print_freq !== undefined && (local_index % print_freq === 0)) {
44
+ if (verbosity !== undefined && (local_index % verbosity === 0)) {
45
45
  console.log(iterator_id + ":" + local_index + "/" + inputs.length)
46
46
  }
47
47
  const output = await this.safe_run(() => f(inputs[local_index], iterator_id, local_index))
@@ -53,6 +53,31 @@ export class UtilsMisc {
53
53
  return outputs
54
54
  }
55
55
 
56
+ async batch_iterate<T, U>(inputs : T[], f : (inputs : T[], iterator_id : number, index : number) => Promise<U>,
57
+ options : { batch_size? : number, num_iterators? : number, verbosity? : number | boolean }) {
58
+ const batch_size = options.batch_size || 1
59
+ const num_iterators = options.num_iterators || 0
60
+ const verbosity : number = typeof options.verbosity === "boolean" ? (options.verbosity === true ? 1 : 0) : (options.verbosity || 0)
61
+ let index = 0
62
+ let iterators = []
63
+ const outputs : (U | undefined)[] = new Array(inputs.length).fill(undefined)
64
+ for (let iterator_id = 0; iterator_id < num_iterators; iterator_id++) {
65
+ iterators.push((async () => {
66
+ while (index < inputs.length) {
67
+ const local_index = index
68
+ index += batch_size
69
+ if (verbosity !== undefined && (local_index % verbosity === 0)) {
70
+ console.log(iterator_id + ":" + local_index + "/" + inputs.length)
71
+ }
72
+ const output = await this.safe_run(() => f(inputs.slice(local_index, local_index + batch_size), iterator_id, local_index))
73
+ outputs[local_index] = output
74
+ }
75
+ })())
76
+ }
77
+ await Promise.all(iterators)
78
+ return outputs
79
+ }
80
+
56
81
 
57
82
  static async wait(duration : number) {
58
83
  return new Promise(resolve => setTimeout(resolve, duration))