@fluentcommerce/fc-connect-sdk 0.1.54 → 0.1.55
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.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/clients/fluent-client.js +13 -6
- package/dist/cjs/utils/pagination-helpers.js +38 -2
- package/dist/cjs/versori/fluent-versori-client.js +11 -5
- package/dist/esm/clients/fluent-client.js +13 -6
- package/dist/esm/utils/pagination-helpers.js +38 -2
- package/dist/esm/versori/fluent-versori-client.js +11 -5
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.types.tsbuildinfo +1 -1
- package/docs/00-START-HERE/EXPORT-VALIDATION.md +158 -158
- package/docs/00-START-HERE/cli-analyze-source-structure-guide.md +655 -655
- package/docs/00-START-HERE/cli-documentation-index.md +202 -202
- package/docs/00-START-HERE/cli-quick-reference.md +252 -252
- package/docs/00-START-HERE/decision-tree.md +552 -552
- package/docs/00-START-HERE/getting-started.md +1070 -1070
- package/docs/00-START-HERE/mapper-quick-decision-guide.md +235 -235
- package/docs/00-START-HERE/readme.md +237 -237
- package/docs/00-START-HERE/retailerid-configuration.md +404 -404
- package/docs/00-START-HERE/sdk-philosophy.md +794 -794
- package/docs/00-START-HERE/troubleshooting-quick-reference.md +1086 -1086
- package/docs/01-TEMPLATES/faq.md +686 -686
- package/docs/01-TEMPLATES/patterns/pattern-templates-guide.md +68 -68
- package/docs/01-TEMPLATES/patterns/patterns-csv-schema-validation-and-rejection-report.md +233 -233
- package/docs/01-TEMPLATES/patterns/patterns-custom-resolvers.md +407 -407
- package/docs/01-TEMPLATES/patterns/patterns-error-handling-retry.md +511 -511
- package/docs/01-TEMPLATES/patterns/patterns-field-mapping-universal.md +701 -701
- package/docs/01-TEMPLATES/patterns/patterns-large-file-splitting.md +1430 -1430
- package/docs/01-TEMPLATES/patterns/patterns-master-data-etl.md +2399 -2399
- package/docs/01-TEMPLATES/patterns/patterns-pagination-streaming.md +447 -447
- package/docs/01-TEMPLATES/patterns/patterns-state-duplicate-prevention.md +385 -385
- package/docs/01-TEMPLATES/readme.md +957 -957
- package/docs/01-TEMPLATES/standalone/standalone-asn-inbound-processing.md +1209 -1209
- package/docs/01-TEMPLATES/standalone/standalone-graphql-query-export.md +1140 -1140
- package/docs/01-TEMPLATES/standalone/standalone-graphql-to-parquet-partitioned-s3.md +432 -432
- package/docs/01-TEMPLATES/standalone/standalone-multi-channel-inventory-sync.md +1185 -1185
- package/docs/01-TEMPLATES/standalone/standalone-multi-source-aggregation.md +1462 -1462
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-batch-api.md +1390 -1390
- package/docs/01-TEMPLATES/standalone/standalone-s3-csv-inventory-to-batch.md +330 -330
- package/docs/01-TEMPLATES/standalone/standalone-scripts-guide.md +87 -87
- package/docs/01-TEMPLATES/standalone/standalone-sftp-xml-graphql.md +1444 -1444
- package/docs/01-TEMPLATES/standalone/standalone-webhook-payload-processing.md +688 -688
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-dropship-order-routing.md +193 -193
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-graphql-parquet-extraction.md +518 -518
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-inter-location-transfers.md +2162 -2162
- package/docs/01-TEMPLATES/versori/business-examples/business-examples-pre-order-allocation.md +2226 -2226
- package/docs/01-TEMPLATES/versori/business-examples/business-scenarios-guide.md +87 -87
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-connection-validation-pattern.md +656 -656
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-dual-workflow-connector.md +835 -835
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-guide.md +108 -108
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-kv-state-management.md +1533 -1533
- package/docs/01-TEMPLATES/versori/patterns/versori-patterns-xml-response-patterns.md +1160 -1160
- package/docs/01-TEMPLATES/versori/versori-platform-guide.md +201 -201
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-asn-purchase-order.md +1906 -1906
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-dropship-routing.md +1074 -1074
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-flash-sale-reserve.md +1395 -1395
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-generic-xml-order.md +888 -888
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-payment-gateway-integration.md +2478 -2478
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-rma-returns-comprehensive.md +2240 -2240
- package/docs/01-TEMPLATES/versori/webhooks/template-webhook-xml-order-ingestion.md +2029 -2029
- package/docs/01-TEMPLATES/versori/webhooks/webhook-templates-guide.md +140 -140
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/inventory-mapping.json +20 -20
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/products_2025-01-22.csv +11 -11
- package/docs/01-TEMPLATES/versori/workflows/_examples/sample-data/sample-data-guide.md +34 -34
- package/docs/01-TEMPLATES/versori/workflows/_examples/workflow-examples-guide.md +36 -36
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-modes-guide.md +1038 -1038
- package/docs/01-TEMPLATES/versori/workflows/extraction/extraction-workflows-guide.md +138 -138
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/graphql-extraction-guide.md +63 -63
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-csv.md +2062 -2062
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-fulfillments-to-sftp-xml.md +2294 -2294
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-s3-csv.md +2461 -2461
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-positions-to-sftp-xml.md +2529 -2529
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-csv.md +2464 -2464
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-inventory-quantities-to-s3-json.md +1959 -1959
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-s3-csv.md +1953 -1953
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-orders-to-sftp-xml.md +2541 -2541
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-s3-json.md +2384 -2384
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-products-to-sftp-xml.md +2445 -2445
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-csv.md +2355 -2355
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-s3-json.md +2042 -2042
- package/docs/01-TEMPLATES/versori/workflows/extraction/graphql-queries/template-extraction-virtual-positions-to-sftp-xml.md +2726 -2726
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/batch-api-guide.md +206 -206
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-cycle-count-reconciliation.md +2030 -2030
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-multi-channel-inventory-sync.md +1882 -1882
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-csv-inventory-batch.md +2827 -2827
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-json-inventory-batch.md +1952 -1952
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-s3-xml-inventory-batch.md +3289 -3289
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-csv-inventory-batch.md +3064 -3064
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-json-inventory-batch.md +3238 -3238
- package/docs/01-TEMPLATES/versori/workflows/ingestion/batch-api/template-ingestion-sftp-xml-inventory-batch.md +2977 -2977
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/event-api-guide.md +321 -321
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-json-order-cancel-event.md +959 -959
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-payload-xml-order-cancel-event.md +1170 -1170
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-csv-product-event.md +2312 -2312
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-json-product-event.md +2999 -2999
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-parquet-product-event.md +2836 -2836
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-s3-xml-product-event.md +2395 -2395
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-csv-product-event.md +2295 -2295
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-json-product-event.md +2602 -2602
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-parquet-product-event.md +2589 -2589
- package/docs/01-TEMPLATES/versori/workflows/ingestion/event-api/template-ingestion-sftp-xml-product-event.md +3578 -3578
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/graphql-mutations-guide.md +93 -93
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-json-order-update-graphql.md +1260 -1260
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-payload-xml-order-update-graphql.md +1472 -1472
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-control-graphql.md +2417 -2417
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-location-graphql.md +2811 -2811
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-csv-price-graphql.md +2619 -2619
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-json-location-graphql.md +2807 -2807
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-s3-xml-location-graphql.md +2373 -2373
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-control-graphql.md +2740 -2740
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-csv-location-graphql.md +2760 -2760
- package/docs/01-TEMPLATES/versori/workflows/ingestion/graphql-mutations/template-ingestion-sftp-json-location-graphql.md +1710 -1710
- package/docs/01-TEMPLATES/versori/workflows/ingestion/ingestion-workflows-guide.md +136 -136
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/rubix-webhooks-guide.md +520 -520
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-inline.md +1418 -1418
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-fulfilment-to-sftp-xml-universal-mapper.md +1785 -1785
- package/docs/01-TEMPLATES/versori/workflows/rubix-webhooks/template-webhook-rubix-order-attribute-update.md +824 -824
- package/docs/01-TEMPLATES/versori/workflows/workflows-overview-guide.md +646 -646
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-batch-archival.md +724 -724
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-job-tracker.md +627 -627
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-partial-batch-recovery.md +561 -561
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-quick-reference.md +367 -367
- package/docs/02-CORE-GUIDES/advanced-services/advanced-services-readme.md +407 -407
- package/docs/02-CORE-GUIDES/advanced-services/readme.md +49 -49
- package/docs/02-CORE-GUIDES/api-reference/api-reference-quick-reference.md +548 -548
- package/docs/02-CORE-GUIDES/api-reference/event-api-input-output-reference.md +702 -1171
- package/docs/02-CORE-GUIDES/api-reference/examples/client-initialization.ts +286 -286
- package/docs/02-CORE-GUIDES/api-reference/graphql-error-classification.md +337 -337
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-01-client-api.md +399 -520
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-03-authentication.md +199 -199
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-04-graphql-mapping.md +925 -925
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-05-services.md +1198 -1198
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-06-data-sources.md +1083 -1083
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-07-parsers.md +1097 -1097
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-pagination.md +513 -513
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-08-types.md +545 -597
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-error-handling.md +527 -527
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-09-webhook-validation.md +514 -514
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-extraction.md +557 -557
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-10-utilities.md +412 -412
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-cli-tools.md +423 -423
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-11-error-handling.md +716 -716
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-analyze-source-structure.md +518 -518
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-partial-responses.md +212 -212
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-12-testing.md +300 -300
- package/docs/02-CORE-GUIDES/api-reference/modules/api-reference-13-resolver-builder.md +322 -322
- package/docs/02-CORE-GUIDES/api-reference/readme.md +279 -279
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-quick-reference.md +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/auto-pagination-readme.md +277 -277
- package/docs/02-CORE-GUIDES/auto-pagination/examples/auto-pagination-readme.md +178 -178
- package/docs/02-CORE-GUIDES/auto-pagination/examples/common-patterns.ts +351 -351
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-products.ts +384 -384
- package/docs/02-CORE-GUIDES/auto-pagination/examples/paginate-virtual-positions.ts +308 -308
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-01-foundations.md +470 -470
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-02-quick-start.md +713 -713
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-03-configuration.md +754 -754
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-04-advanced-patterns.md +732 -732
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-05-sdk-integration.md +847 -847
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-06-troubleshooting.md +359 -359
- package/docs/02-CORE-GUIDES/auto-pagination/modules/auto-pagination-07-api-reference.md +462 -462
- package/docs/02-CORE-GUIDES/auto-pagination/readme.md +54 -54
- package/docs/02-CORE-GUIDES/data-sources/data-sources-file-operations-error-handling.md +1487 -1487
- package/docs/02-CORE-GUIDES/data-sources/data-sources-quick-reference.md +836 -836
- package/docs/02-CORE-GUIDES/data-sources/data-sources-readme.md +276 -276
- package/docs/02-CORE-GUIDES/data-sources/data-sources-sftp-credential-access-security.md +553 -553
- package/docs/02-CORE-GUIDES/data-sources/examples/common-patterns.ts +409 -409
- package/docs/02-CORE-GUIDES/data-sources/examples/data-sources-readme.md +178 -178
- package/docs/02-CORE-GUIDES/data-sources/examples/s3-operations.ts +308 -308
- package/docs/02-CORE-GUIDES/data-sources/examples/sftp-operations.ts +371 -371
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-01-foundations.md +735 -735
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-02-s3-operations.md +1302 -1302
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-03-sftp-operations.md +1379 -1379
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-04-file-patterns.md +941 -941
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-05-advanced-topics.md +813 -813
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-06-integration-patterns.md +486 -486
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-07-troubleshooting.md +387 -387
- package/docs/02-CORE-GUIDES/data-sources/modules/data-sources-08-api-reference.md +417 -417
- package/docs/02-CORE-GUIDES/data-sources/readme.md +77 -77
- package/docs/02-CORE-GUIDES/error-handling-guide.md +936 -936
- package/docs/02-CORE-GUIDES/extraction/examples/02-core-guides-extraction-readme.md +116 -116
- package/docs/02-CORE-GUIDES/extraction/examples/common-patterns.ts +428 -428
- package/docs/02-CORE-GUIDES/extraction/examples/extract-inventory-basic.ts +187 -187
- package/docs/02-CORE-GUIDES/extraction/extraction-quick-reference.md +596 -596
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-01-foundations.md +514 -514
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-02-basic-extraction.md +823 -823
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-03-parquet-processing.md +507 -507
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-04-data-enrichment.md +546 -546
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-05-transformation.md +494 -494
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-export-formats.md +458 -458
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-06-performance.md +138 -138
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-api-reference.md +148 -148
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-07-optimization.md +692 -692
- package/docs/02-CORE-GUIDES/extraction/modules/02-core-guides-extraction-08-extraction-orchestrator.md +1008 -1008
- package/docs/02-CORE-GUIDES/extraction/readme.md +151 -151
- package/docs/02-CORE-GUIDES/ingestion/examples/_simple-kv-store.ts +40 -40
- package/docs/02-CORE-GUIDES/ingestion/examples/error-recovery.ts +728 -728
- package/docs/02-CORE-GUIDES/ingestion/examples/event-driven.ts +501 -501
- package/docs/02-CORE-GUIDES/ingestion/examples/local-file-ingestion.ts +88 -88
- package/docs/02-CORE-GUIDES/ingestion/examples/parquet-ingestion.ts +117 -117
- package/docs/02-CORE-GUIDES/ingestion/examples/performance-optimized.ts +647 -647
- package/docs/02-CORE-GUIDES/ingestion/examples/s3-csv-ingestion.ts +169 -169
- package/docs/02-CORE-GUIDES/ingestion/examples/sftp-csv-ingestion.ts +134 -134
- package/docs/02-CORE-GUIDES/ingestion/ingestion-quick-reference.md +546 -546
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-01-introduction.md +626 -626
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-02-quick-start.md +658 -658
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-03-data-sources.md +1052 -1052
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-04-field-mapping.md +763 -763
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-05-advanced-parsers.md +676 -676
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-06-batch-api.md +1295 -1295
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-api-reference.md +138 -138
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-07-state-management.md +1037 -1037
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-08-performance-optimization.md +1349 -1349
- package/docs/02-CORE-GUIDES/ingestion/modules/02-core-guides-ingestion-09-best-practices.md +1893 -1893
- package/docs/02-CORE-GUIDES/ingestion/readme.md +160 -160
- package/docs/02-CORE-GUIDES/logging-guide.md +585 -585
- package/docs/02-CORE-GUIDES/mapping/error-handling-patterns.md +401 -401
- package/docs/02-CORE-GUIDES/mapping/examples/02-core-guides-mapping-readme.md +128 -128
- package/docs/02-CORE-GUIDES/mapping/examples/common-patterns.ts +273 -273
- package/docs/02-CORE-GUIDES/mapping/examples/csv-location-ingestion.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/csv-mapping.ts +242 -242
- package/docs/02-CORE-GUIDES/mapping/examples/graphql-to-parquet-extraction.json +36 -36
- package/docs/02-CORE-GUIDES/mapping/examples/json-mapping.ts +213 -213
- package/docs/02-CORE-GUIDES/mapping/examples/json-product-to-mutation.json +48 -48
- package/docs/02-CORE-GUIDES/mapping/examples/xml-mapping.ts +291 -291
- package/docs/02-CORE-GUIDES/mapping/examples/xml-order-to-mutation.json +45 -45
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-quick-reference.md +463 -463
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/graphql-mutation-mapping-readme.md +227 -227
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-01-introduction.md +222 -222
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-02-quick-start.md +351 -351
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-03-schema-validation.md +569 -569
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-04-mapping-patterns.md +471 -471
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-05-configuration-reference.md +611 -611
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-advanced-xpath.md +148 -148
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-06-path-syntax.md +464 -464
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-api-reference.md +94 -94
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-07-array-handling.md +307 -307
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-08-custom-resolvers.md +544 -544
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-09-advanced-patterns.md +427 -427
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-10-hooks-and-variables.md +336 -336
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-11-error-handling.md +488 -488
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-12-arguments-vs-nodes.md +383 -383
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/modules/graphql-mutation-mapping-13-best-practices.md +477 -477
- package/docs/02-CORE-GUIDES/mapping/graphql-mutation-mapping/readme.md +62 -62
- package/docs/02-CORE-GUIDES/mapping/mapping-format-decision-tree.md +480 -480
- package/docs/02-CORE-GUIDES/mapping/mapping-graphql-alias-batching-guide.md +820 -820
- package/docs/02-CORE-GUIDES/mapping/mapping-javascript-objects.md +2369 -2369
- package/docs/02-CORE-GUIDES/mapping/mapping-mapper-comparison-guide.md +682 -682
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-07-api-reference.md +1327 -1327
- package/docs/02-CORE-GUIDES/mapping/modules/02-core-guides-mapping-08-error-handling.md +1142 -1142
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-04-use-cases.md +891 -891
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-helpers-resolvers.md +1126 -1126
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-06-sdk-resolvers.md +199 -199
- package/docs/02-CORE-GUIDES/mapping/modules/mapping-07-api-reference.md +1319 -1319
- package/docs/02-CORE-GUIDES/mapping/readme.md +178 -178
- package/docs/02-CORE-GUIDES/mapping/resolver-registration.md +410 -410
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/common-patterns.ts +226 -226
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/custom-resolvers.ts +227 -227
- package/docs/02-CORE-GUIDES/mapping/resolvers/examples/sdk-resolvers-usage.ts +203 -203
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-readme.md +274 -274
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-api-reference.md +679 -679
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-cookbook.md +826 -826
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-guide.md +1330 -1330
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-helpers-reference.md +1437 -1437
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-parameters-reference.md +553 -553
- package/docs/02-CORE-GUIDES/mapping/resolvers/mapping-resolvers-resolver-troubleshooting.md +854 -854
- package/docs/02-CORE-GUIDES/mapping/resolvers/readme.md +75 -75
- package/docs/02-CORE-GUIDES/parsers/examples/02-core-guides-parsers-readme.md +161 -161
- package/docs/02-CORE-GUIDES/parsers/examples/csv-parser-examples.ts +110 -110
- package/docs/02-CORE-GUIDES/parsers/examples/json-parser-examples.ts +33 -33
- package/docs/02-CORE-GUIDES/parsers/examples/parquet-parser-examples.ts +47 -47
- package/docs/02-CORE-GUIDES/parsers/examples/xml-parser-examples.ts +38 -38
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-01-foundations.md +355 -355
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-02-csv-parser.md +772 -772
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-03-json-parser.md +789 -789
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-04-xml-parser.md +857 -857
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-05-parquet-parser.md +603 -603
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-integration-patterns.md +702 -702
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-06-streaming.md +121 -121
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-api-reference.md +89 -89
- package/docs/02-CORE-GUIDES/parsers/modules/02-core-guides-parsers-07-troubleshooting.md +727 -727
- package/docs/02-CORE-GUIDES/parsers/parsers-quick-reference.md +482 -482
- package/docs/02-CORE-GUIDES/parsers/parsers-readme.md +258 -258
- package/docs/02-CORE-GUIDES/parsers/readme.md +65 -65
- package/docs/02-CORE-GUIDES/readme.md +194 -194
- package/docs/02-CORE-GUIDES/webhook-validation/examples/basic-validation.ts +108 -108
- package/docs/02-CORE-GUIDES/webhook-validation/examples/common-patterns.ts +316 -316
- package/docs/02-CORE-GUIDES/webhook-validation/examples/webhook-validation-readme.md +61 -61
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-01-foundations.md +440 -440
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-02-quick-start.md +525 -525
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-03-versori-integration.md +741 -741
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-04-platform-integration.md +629 -629
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-05-configuration.md +535 -535
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-error-handling.md +611 -611
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-06-troubleshooting.md +124 -124
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-07-api-reference.md +511 -511
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-08-rubix-webhooks.md +590 -590
- package/docs/02-CORE-GUIDES/webhook-validation/modules/webhook-validation-09-rubix-event-vs-http-call.md +432 -432
- package/docs/02-CORE-GUIDES/webhook-validation/readme.md +239 -239
- package/docs/02-CORE-GUIDES/webhook-validation/webhook-validation-quick-reference.md +392 -392
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-quick-reference.md +498 -498
- package/docs/03-PATTERN-GUIDES/connector-scenarios/connector-scenarios-readme.md +313 -313
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/common-patterns.ts +612 -612
- package/docs/03-PATTERN-GUIDES/connector-scenarios/examples/connector-scenarios-readme.md +253 -253
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-01-foundations.md +452 -452
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-02-simple-scenarios.md +681 -681
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-03-intermediate-scenarios.md +637 -637
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-04-advanced-scenarios.md +650 -650
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-05-bidirectional-sync.md +233 -233
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-06-production-patterns.md +442 -442
- package/docs/03-PATTERN-GUIDES/connector-scenarios/modules/connector-scenarios-07-reference.md +445 -445
- package/docs/03-PATTERN-GUIDES/connector-scenarios/readme.md +31 -31
- package/docs/03-PATTERN-GUIDES/enterprise-integration-patterns.md +1528 -1528
- package/docs/03-PATTERN-GUIDES/error-handling/comprehensive-error-handling-guide.md +1437 -1437
- package/docs/03-PATTERN-GUIDES/error-handling/error-handling-quick-reference.md +390 -390
- package/docs/03-PATTERN-GUIDES/error-handling/examples/common-patterns.ts +438 -438
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-01-foundations.md +362 -362
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-02-error-types.md +850 -850
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-03-utf8-handling.md +456 -456
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-04-error-scenarios.md +658 -658
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-05-calling-patterns.md +671 -671
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-06-retry-strategies.md +1034 -1034
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-07-monitoring.md +653 -653
- package/docs/03-PATTERN-GUIDES/error-handling/modules/error-handling-08-api-reference.md +847 -847
- package/docs/03-PATTERN-GUIDES/error-handling/readme.md +36 -36
- package/docs/03-PATTERN-GUIDES/examples/__tests__/readme.md +40 -40
- package/docs/03-PATTERN-GUIDES/examples/__tests__/resolver-examples.test.js +282 -282
- package/docs/03-PATTERN-GUIDES/examples/test-data/03-pattern-guides-readme.md +110 -110
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-inventory.json +123 -123
- package/docs/03-PATTERN-GUIDES/examples/test-data/canonical-order.json +171 -171
- package/docs/03-PATTERN-GUIDES/examples/test-data/readme.md +28 -28
- package/docs/03-PATTERN-GUIDES/extraction/extraction-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/extraction/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/file-operations/examples/common-patterns.ts +407 -407
- package/docs/03-PATTERN-GUIDES/file-operations/examples/file-operations-readme.md +142 -142
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-quick-reference.md +462 -462
- package/docs/03-PATTERN-GUIDES/file-operations/file-operations-readme.md +379 -379
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-01-foundations.md +430 -430
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-02-quick-start.md +484 -484
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-03-s3-operations.md +507 -507
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-04-sftp-operations.md +963 -963
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-05-streaming-performance.md +503 -503
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-archive-patterns.md +386 -386
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-06-error-handling.md +117 -117
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-api-reference.md +78 -78
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-07-testing-troubleshooting.md +567 -567
- package/docs/03-PATTERN-GUIDES/file-operations/modules/file-operations-08-api-reference.md +1055 -1055
- package/docs/03-PATTERN-GUIDES/file-operations/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/ingestion/ingestion-readme.md +15 -15
- package/docs/03-PATTERN-GUIDES/ingestion/readme.md +25 -25
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/batch-processing.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/common-patterns.ts +360 -360
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/delta-sync.ts +130 -130
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/integration-patterns-readme.md +100 -100
- package/docs/03-PATTERN-GUIDES/integration-patterns/examples/real-time-webhook.ts +398 -398
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-quick-reference.md +962 -962
- package/docs/03-PATTERN-GUIDES/integration-patterns/integration-patterns-readme.md +134 -134
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-01-real-time-processing.md +991 -991
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-02-batch-processing.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-03-delta-sync.md +1108 -1108
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-04-webhook-patterns.md +1181 -1181
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-05-error-handling.md +1061 -1061
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-advanced-integration-services.md +1547 -1547
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-06-performance.md +109 -109
- package/docs/03-PATTERN-GUIDES/integration-patterns/modules/integration-patterns-07-api-reference.md +34 -34
- package/docs/03-PATTERN-GUIDES/integration-patterns/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/logging-minimal-mode.md +128 -128
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/common-patterns.ts +380 -380
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/multiple-connections-readme.md +139 -139
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/parallel-root-connections.ts +149 -149
- package/docs/03-PATTERN-GUIDES/multiple-connections/examples/real-world-scenarios.ts +405 -405
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-01-foundations.md +378 -378
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-02-quick-start.md +566 -566
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-03-targeting-connections.md +659 -659
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-04-parallel-queries.md +656 -656
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-05-best-practices.md +624 -624
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-api-reference.md +824 -824
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-06-versori.md +119 -119
- package/docs/03-PATTERN-GUIDES/multiple-connections/modules/multiple-connections-07-api-reference.md +87 -87
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-quick-reference.md +353 -353
- package/docs/03-PATTERN-GUIDES/multiple-connections/multiple-connections-readme.md +270 -270
- package/docs/03-PATTERN-GUIDES/multiple-connections/readme.md +30 -30
- package/docs/03-PATTERN-GUIDES/pagination/pagination-readme.md +14 -14
- package/docs/03-PATTERN-GUIDES/pagination/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/parquet/examples/common-patterns.ts +180 -180
- package/docs/03-PATTERN-GUIDES/parquet/examples/read-parquet.ts +48 -48
- package/docs/03-PATTERN-GUIDES/parquet/examples/write-parquet.ts +65 -65
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-01-introduction.md +393 -393
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-02-quick-start.md +572 -572
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-03-reading-parquet.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-04-writing-parquet.md +554 -554
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-05-graphql-extraction.md +405 -405
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-performance.md +104 -104
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-06-s3-integration.md +511 -511
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-api-reference.md +90 -90
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-07-performance-optimization.md +525 -525
- package/docs/03-PATTERN-GUIDES/parquet/modules/03-pattern-guides-parquet-08-best-practices.md +712 -712
- package/docs/03-PATTERN-GUIDES/parquet/parquet-quick-reference.md +683 -683
- package/docs/03-PATTERN-GUIDES/parquet/parquet-readme.md +248 -248
- package/docs/03-PATTERN-GUIDES/parquet/readme.md +32 -32
- package/docs/03-PATTERN-GUIDES/parsers/parsers-readme.md +12 -12
- package/docs/03-PATTERN-GUIDES/parsers/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/readme.md +159 -159
- package/docs/03-PATTERN-GUIDES/webhooks/readme.md +24 -24
- package/docs/03-PATTERN-GUIDES/webhooks/webhooks-readme.md +8 -8
- package/docs/04-REFERENCE/architecture/architecture-01-overview.md +427 -427
- package/docs/04-REFERENCE/architecture/architecture-02-client-architecture.md +424 -424
- package/docs/04-REFERENCE/architecture/architecture-03-data-flow.md +690 -690
- package/docs/04-REFERENCE/architecture/architecture-04-service-layer.md +834 -834
- package/docs/04-REFERENCE/architecture/architecture-05-integration-architecture.md +655 -655
- package/docs/04-REFERENCE/architecture/architecture-06-state-management.md +653 -653
- package/docs/04-REFERENCE/architecture/architecture-adding-new-data-sources.md +686 -686
- package/docs/04-REFERENCE/architecture/readme.md +279 -279
- package/docs/04-REFERENCE/platforms/deno/readme.md +117 -117
- package/docs/04-REFERENCE/platforms/nodejs/readme.md +146 -146
- package/docs/04-REFERENCE/platforms/readme.md +135 -135
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-01-introduction.md +398 -398
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-02-quick-start.md +560 -560
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-03-authentication.md +757 -757
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-04-workflows.md +2476 -2476
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-05-connections.md +1167 -1167
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-kv-storage.md +990 -990
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-06-state-management.md +121 -121
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-api-reference.md +68 -68
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-07-deployment.md +731 -731
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-08-best-practices.md +1111 -1111
- package/docs/04-REFERENCE/platforms/versori/modules/platforms-versori-09-signature-reference.md +766 -766
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-readme.md +299 -299
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-s3-sftp-configuration-guide.md +1425 -1425
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-api-key-security.md +816 -816
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-webhook-connection-security.md +681 -681
- package/docs/04-REFERENCE/platforms/versori/platforms-versori-workflow-task-types.md +708 -708
- package/docs/04-REFERENCE/platforms/versori/readme.md +108 -108
- package/docs/04-REFERENCE/readme.md +148 -148
- package/docs/04-REFERENCE/resolver-signature/examples/advanced-resolvers.ts +482 -482
- package/docs/04-REFERENCE/resolver-signature/examples/async-resolvers.ts +496 -496
- package/docs/04-REFERENCE/resolver-signature/examples/basic-resolvers.ts +343 -343
- package/docs/04-REFERENCE/resolver-signature/examples/resolver-signature-readme.md +188 -188
- package/docs/04-REFERENCE/resolver-signature/examples/testing-resolvers.ts +463 -463
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-01-foundations.md +286 -286
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-02-parameter-reference.md +643 -643
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-03-basic-examples.md +521 -521
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-04-advanced-patterns.md +739 -739
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-05-sdk-resolvers.md +531 -531
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-migration-guide.md +650 -650
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-06-testing.md +125 -125
- package/docs/04-REFERENCE/resolver-signature/modules/resolver-signature-07-api-reference.md +794 -794
- package/docs/04-REFERENCE/resolver-signature/readme.md +64 -64
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-quick-reference.md +270 -270
- package/docs/04-REFERENCE/resolver-signature/resolver-signature-readme.md +351 -351
- package/docs/04-REFERENCE/schema/fluent-commerce-schema.json +764 -764
- package/docs/04-REFERENCE/schema/readme.md +141 -141
- package/docs/04-REFERENCE/testing/examples/04-reference-testing-readme.md +158 -158
- package/docs/04-REFERENCE/testing/examples/fluent-testing.ts +62 -62
- package/docs/04-REFERENCE/testing/examples/health-check.ts +155 -155
- package/docs/04-REFERENCE/testing/examples/integration-test.ts +119 -119
- package/docs/04-REFERENCE/testing/examples/performance-test.ts +183 -183
- package/docs/04-REFERENCE/testing/examples/s3-testing.ts +127 -127
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-01-foundations.md +267 -267
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-02-s3-testing.md +599 -599
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-03-fluent-testing.md +589 -589
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-04-integration-testing.md +699 -699
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-05-debugging.md +478 -478
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-cicd-integration.md +463 -463
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-06-preflight-validation.md +131 -131
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-best-practices.md +499 -499
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-07-coverage-ci.md +165 -165
- package/docs/04-REFERENCE/testing/modules/04-reference-testing-08-api-reference.md +634 -634
- package/docs/04-REFERENCE/testing/readme.md +86 -86
- package/docs/04-REFERENCE/testing/testing-quick-reference.md +667 -667
- package/docs/04-REFERENCE/testing/testing-readme.md +286 -286
- package/docs/04-REFERENCE/troubleshooting/readme.md +144 -144
- package/docs/04-REFERENCE/troubleshooting/troubleshooting-deno-sftp-compatibility.md +392 -392
- package/docs/template-loading-matrix.md +242 -242
- package/package.json +5 -3
- package/docs/02-CORE-GUIDES/api-reference/cli-profile-integration.md +0 -377
|
@@ -1,708 +1,708 @@
|
|
|
1
|
-
# Versori Workflow Task Types - Complete Reference
|
|
2
|
-
|
|
3
|
-
**@versori/run Package Version**: v0.4.8 (verified from npm)
|
|
4
|
-
**SDK Compatibility**: Use latest @fluentcommerce/fc-connect-sdk
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Table of Contents
|
|
9
|
-
|
|
10
|
-
1. [Overview](#overview)
|
|
11
|
-
2. [Task Chaining Methods](#task-chaining-methods)
|
|
12
|
-
3. [Parallel Processing with `.unpack()`](#parallel-processing-with-unpack)
|
|
13
|
-
4. [Serial Processing](#serial-processing)
|
|
14
|
-
5. [Working Examples](#working-examples)
|
|
15
|
-
6. [Performance Characteristics](#performance-characteristics)
|
|
16
|
-
7. [Platform Constraints](#platform-constraints)
|
|
17
|
-
8. [Decision Matrix](#decision-matrix)
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Overview
|
|
22
|
-
|
|
23
|
-
Versori's `@versori/run` package provides a fluent API for building workflows with support for parallel and serial array processing. All Task types (`fn`, `http`, `schedule`) support the full chain of methods including `.unpack()` and `.parallel()`.
|
|
24
|
-
|
|
25
|
-
### Core Task Methods
|
|
26
|
-
|
|
27
|
-
| Method | Returns | Purpose | Code Location |
|
|
28
|
-
|--------|---------|---------|---------------|
|
|
29
|
-
| `.then()` | `Task` | Chain next task | `Task.d.ts:20` |
|
|
30
|
-
| `.catch()` | `Task` | Handle errors | `Task.d.ts:29` |
|
|
31
|
-
| `.background()` | `Task` | Run in background | `Task.d.ts:34` |
|
|
32
|
-
| `.unpack()` | `ArrayTask` | Split array into elements | `Task.d.ts:35-36` |
|
|
33
|
-
| `.clone()` | `Task` | Clone task | `Task.d.ts:40` |
|
|
34
|
-
|
|
35
|
-
### ArrayTask Methods (after unpack())
|
|
36
|
-
|
|
37
|
-
| Method | Returns | Purpose | Code Location |
|
|
38
|
-
|--------|---------|---------|---------------|
|
|
39
|
-
| `.parallel()` | `Task` | Process array elements in parallel | `Task.d.ts:59` |
|
|
40
|
-
| `.serial()` | `Task` | Process array elements sequentially | `Task.d.ts:67` |
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## Task Chaining Methods
|
|
45
|
-
|
|
46
|
-
### 1. `.then<NextOut>(task)` → `Task<In, NextOut>`
|
|
47
|
-
|
|
48
|
-
Chain the next task after current task completes.
|
|
49
|
-
|
|
50
|
-
**Implementation**: `Task.d.ts:20` in `@versori/run` package
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
schedule('example', '0 * * * *')
|
|
54
|
-
.then(fn('step1', (ctx) => ({ result: 'data' })))
|
|
55
|
-
.then(fn('step2', (ctx) => {
|
|
56
|
-
console.log(ctx.data.result); // 'data'
|
|
57
|
-
return { next: 'value' };
|
|
58
|
-
}));
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### 2. `.catch<NextOut>(task)` → `Task<In, NextOut>`
|
|
62
|
-
|
|
63
|
-
Handle errors from previous task. Workflow continues after catch.
|
|
64
|
-
|
|
65
|
-
**Implementation**: `Task.d.ts:29` in `@versori/run` package
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
schedule('example', '0 * * * *')
|
|
69
|
-
.then(fn('may-fail', (ctx) => {
|
|
70
|
-
throw new Error('Something failed');
|
|
71
|
-
}))
|
|
72
|
-
.catch(fn('handle-error', (ctx) => {
|
|
73
|
-
console.error(ctx.data); // Error object
|
|
74
|
-
return { recovered: true };
|
|
75
|
-
}));
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### 3. `.background()` → `Task<In, void>`
|
|
79
|
-
|
|
80
|
-
Run task in background. Next task receives `void` as input.
|
|
81
|
-
|
|
82
|
-
**Implementation**: `Task.d.ts:34` in `@versori/run` package
|
|
83
|
-
|
|
84
|
-
```typescript
|
|
85
|
-
schedule('example', '0 * * * *')
|
|
86
|
-
.then(fn('long-running', (ctx) => {
|
|
87
|
-
// Long operation
|
|
88
|
-
}))
|
|
89
|
-
.background() // Doesn't wait for completion
|
|
90
|
-
.then(fn('continues-immediately', (ctx) => {
|
|
91
|
-
// ctx.data is void
|
|
92
|
-
}));
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## Parallel Processing with unpack()
|
|
98
|
-
|
|
99
|
-
### `.unpack()` Method
|
|
100
|
-
|
|
101
|
-
Splits an array output into individual elements, returning an `ArrayTask` that provides `.parallel()` and `.serial()` methods.
|
|
102
|
-
|
|
103
|
-
**Signatures**:
|
|
104
|
-
```typescript
|
|
105
|
-
// Auto-unpack array
|
|
106
|
-
unpack<NextOut = Out extends Array<infer Elem> ? Elem : Out>(): ArrayTask<In, NextOut>
|
|
107
|
-
|
|
108
|
-
// Custom mapper
|
|
109
|
-
unpack<NextOut>(mapper: (data: Out) => NextOut[]): ArrayTask<In, NextOut>
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
**Implementation Locations**:
|
|
113
|
-
- Interface: `Task.d.ts:35-36`
|
|
114
|
-
- FnTask: `FnTask.js:52-57`
|
|
115
|
-
- HttpTask: `HttpTask.js:70-75`
|
|
116
|
-
- UnpackTask class: `UnpackTask.js`
|
|
117
|
-
- Compiler: `unpack.js:21-30`
|
|
118
|
-
|
|
119
|
-
All files are in the `@versori/run` package under `node_modules/@versori/run/esm/src/`
|
|
120
|
-
|
|
121
|
-
### `.parallel()` Method
|
|
122
|
-
|
|
123
|
-
Process each array element concurrently using RxJS `mergeMap`.
|
|
124
|
-
|
|
125
|
-
**Signature**:
|
|
126
|
-
```typescript
|
|
127
|
-
parallel<NextOut>(task: Taskable<OutElem, NextOut, number>): Task<In, NextOut[]>
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
**Implementation Locations** in `@versori/run` package:
|
|
131
|
-
- Interface: `Task.d.ts:59`
|
|
132
|
-
- UnpackTask: `UnpackTask.js:44-46`
|
|
133
|
-
- ParallelTask class: `ParallelTask.js:25-47`
|
|
134
|
-
- Compiler: `parallel.js:15-27`
|
|
135
|
-
|
|
136
|
-
**Key Characteristics**:
|
|
137
|
-
- ✅ **Maintains order**: Results are sorted by original index
|
|
138
|
-
- ✅ **Type-safe**: Full TypeScript support with generics
|
|
139
|
-
- ✅ **No concurrency limit**: Processes all elements simultaneously
|
|
140
|
-
- ⚠️ **Memory usage**: All results held in memory
|
|
141
|
-
- ⚠️ **Error handling**: One failure stops entire workflow
|
|
142
|
-
- ⚠️ **NOT fault-tolerant**: If any task fails, **all results are lost** (no partial results)
|
|
143
|
-
- ⚠️ **NOT ACID compliant**: No atomicity guarantees, no rollback mechanism
|
|
144
|
-
- ⚠️ **Shared timeout**: All parallel tasks share the same workflow timeout (30s/5min)
|
|
145
|
-
|
|
146
|
-
### ⚠️ CRITICAL: Fault Tolerance Limitations
|
|
147
|
-
|
|
148
|
-
**Problem**: `.parallel()` uses RxJS `mergeMap` + `toArray()` which stops on first error. This means:
|
|
149
|
-
|
|
150
|
-
1. **One failure stops everything**: If any parallel task throws an error, the entire workflow fails
|
|
151
|
-
2. **No partial results**: You won't receive successful results even if most tasks succeeded
|
|
152
|
-
3. **No error isolation**: Failed tasks prevent successful tasks from completing
|
|
153
|
-
|
|
154
|
-
**Example of the problem**:
|
|
155
|
-
|
|
156
|
-
```typescript
|
|
157
|
-
schedule('process-files', '0 2 * * *')
|
|
158
|
-
.then(fn('fetch-files', (ctx) => ['file1.xml', 'file2.xml', 'file3.xml']))
|
|
159
|
-
.unpack()
|
|
160
|
-
.parallel(fn('process-file', async (ctx) => {
|
|
161
|
-
// ❌ If file2.xml fails here...
|
|
162
|
-
return await processFile(ctx.data);
|
|
163
|
-
}));
|
|
164
|
-
|
|
165
|
-
// Result:
|
|
166
|
-
// ✅ file1.xml might complete
|
|
167
|
-
// ❌ file2.xml fails → ENTIRE WORKFLOW FAILS
|
|
168
|
-
// ❌ file3.xml NEVER RUNS (or gets cancelled)
|
|
169
|
-
// ❌ No partial results returned
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
**Why this happens**: The RxJS `toArray()` operator never completes if the stream errors before all items are processed.
|
|
173
|
-
|
|
174
|
-
### ✅ Recommended: Use `Promise.allSettled()` for Fault Tolerance
|
|
175
|
-
|
|
176
|
-
For **production workloads** where failures are expected, use `Promise.allSettled()` inside a `fn()` task:
|
|
177
|
-
|
|
178
|
-
```typescript
|
|
179
|
-
schedule('process-files', '0 2 * * *')
|
|
180
|
-
.then(fn('process-all-files', async (ctx) => {
|
|
181
|
-
const files = ['file1.xml', 'file2.xml', 'file3.xml'];
|
|
182
|
-
|
|
183
|
-
// ✅ Fault-tolerant: Continues even if some fail
|
|
184
|
-
const results = await Promise.allSettled(
|
|
185
|
-
files.map(file => processFile(file))
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
// Process results
|
|
189
|
-
const successes = results
|
|
190
|
-
.filter(r => r.status === 'fulfilled')
|
|
191
|
-
.map(r => r.value);
|
|
192
|
-
|
|
193
|
-
const failures = results
|
|
194
|
-
.filter(r => r.status === 'rejected')
|
|
195
|
-
.map(r => ({ file: r.reason.file, error: r.reason.message }));
|
|
196
|
-
|
|
197
|
-
ctx.log.info(`Processed ${successes.length} files, ${failures.length} failed`);
|
|
198
|
-
|
|
199
|
-
return { successes, failures };
|
|
200
|
-
}));
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**Comparison**:
|
|
204
|
-
|
|
205
|
-
| Feature | `.unpack().parallel()` | `Promise.allSettled()` |
|
|
206
|
-
|---------|------------------------|------------------------|
|
|
207
|
-
| Fault tolerance | ❌ Fails on first error | ✅ Continues on errors |
|
|
208
|
-
| Partial results | ❌ No results if any fail | ✅ Returns all results |
|
|
209
|
-
| Error isolation | ❌ No isolation | ✅ Complete isolation |
|
|
210
|
-
| Best for | All-or-nothing workflows | Real-world with failures |
|
|
211
|
-
|
|
212
|
-
See [Module 4: Workflows](./modules/platforms-versori-04-workflows.md#-critical-parallel-processing-with-unpack-and-parallel) for detailed guidance.
|
|
213
|
-
|
|
214
|
-
### Execution Engine
|
|
215
|
-
|
|
216
|
-
The parallel compiler uses RxJS operators:
|
|
217
|
-
|
|
218
|
-
```javascript
|
|
219
|
-
// From parallel.js:15-27
|
|
220
|
-
function compileParallel(ctx, task) {
|
|
221
|
-
const baseOperator = ctx.compiler.compileTask(ctx, task._base);
|
|
222
|
-
const eachOperator = ctx.compiler.compileTask(ctx, task._each);
|
|
223
|
-
|
|
224
|
-
return (src) => src.pipe(
|
|
225
|
-
baseOperator,
|
|
226
|
-
mergeMap((ctx) => {
|
|
227
|
-
return from(ctx.data).pipe(
|
|
228
|
-
map((data, idx) => ctx.withData(data).setIndex(idx)),
|
|
229
|
-
// Process items in parallel using mergeMap
|
|
230
|
-
mergeMap((item) => eachOperator(of(item)).pipe(
|
|
231
|
-
map((result) => result.setIndex(item.idx))
|
|
232
|
-
)),
|
|
233
|
-
toArray(),
|
|
234
|
-
map((results) => {
|
|
235
|
-
// Sort by original index to maintain order
|
|
236
|
-
results.sort((a, b) => a.idx - b.idx);
|
|
237
|
-
return ctx.withData(results.map((r) => r.data));
|
|
238
|
-
})
|
|
239
|
-
);
|
|
240
|
-
})
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Serial Processing
|
|
248
|
-
|
|
249
|
-
### `.serial()` Method
|
|
250
|
-
|
|
251
|
-
Process each array element sequentially (one after another).
|
|
252
|
-
|
|
253
|
-
**Signature**:
|
|
254
|
-
```typescript
|
|
255
|
-
serial<NextOut>(task: Taskable<OutElem, NextOut, number>): Task<In, NextOut[]>
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
**Implementation** in `@versori/run` package:
|
|
259
|
-
- Interface: `Task.d.ts:67`
|
|
260
|
-
- UnpackTask: `UnpackTask.js:48-50`
|
|
261
|
-
- SerialTask class: `SerialTask.js`
|
|
262
|
-
- Compiler: `serial.js`
|
|
263
|
-
|
|
264
|
-
**Use When**:
|
|
265
|
-
- Order of execution matters
|
|
266
|
-
- Items depend on previous items
|
|
267
|
-
- Rate limiting required
|
|
268
|
-
- Precise progress tracking needed
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## Working Examples
|
|
273
|
-
|
|
274
|
-
### Example 1: Parallel File Processing
|
|
275
|
-
|
|
276
|
-
Process multiple SFTP XML files concurrently:
|
|
277
|
-
|
|
278
|
-
```typescript
|
|
279
|
-
import { schedule, fn, http } from '@versori/run';
|
|
280
|
-
import { createClient, SftpDataSource } from '@fluentcommerce/fc-connect-sdk';
|
|
281
|
-
|
|
282
|
-
export const parallelFileProcessing = schedule('parallel-files', '0 */6 * * *')
|
|
283
|
-
.then(fn('list-files', async (ctx) => {
|
|
284
|
-
const sftp = new SftpDataSource(sftpConfig, ctx.log);
|
|
285
|
-
await sftp.connect();
|
|
286
|
-
|
|
287
|
-
const files = await sftp.listFiles({
|
|
288
|
-
remotePath: '/incoming/inventory/',
|
|
289
|
-
filePattern: '.xml'
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
await sftp.disconnect();
|
|
293
|
-
|
|
294
|
-
return files; // Array of file metadata
|
|
295
|
-
}))
|
|
296
|
-
.unpack() // Split array into individual files
|
|
297
|
-
.parallel( // Process each file concurrently
|
|
298
|
-
http('process-file', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
299
|
-
const file = ctx.data; // Single file metadata
|
|
300
|
-
const client = await createClient(ctx);
|
|
301
|
-
|
|
302
|
-
// Download and process file
|
|
303
|
-
const sftp = new SftpDataSource(sftpConfig, ctx.log);
|
|
304
|
-
await sftp.connect();
|
|
305
|
-
const content = await sftp.downloadFile(file.path);
|
|
306
|
-
await sftp.disconnect();
|
|
307
|
-
|
|
308
|
-
// Parse, map, and send to Fluent
|
|
309
|
-
const records = await parseAndMap(content);
|
|
310
|
-
const job = await client.createJob({ name: `Process ${file.name}` });
|
|
311
|
-
await client.sendBatch(job.id, {
|
|
312
|
-
action: 'UPSERT',
|
|
313
|
-
entityType: 'INVENTORY_POSITION',
|
|
314
|
-
entities: records
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
return { file: file.name, jobId: job.id, recordCount: records.length };
|
|
318
|
-
})
|
|
319
|
-
);
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
**Performance**:
|
|
323
|
-
- 10 files × 30s each = 300s (sequential)
|
|
324
|
-
- 10 files processed simultaneously = 30s (parallel)
|
|
325
|
-
- **10x speedup**
|
|
326
|
-
|
|
327
|
-
### Example 2: Custom Batching with Mapper
|
|
328
|
-
|
|
329
|
-
Group items into batches, then process batches in parallel:
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
export const batchedParallelProcessing = schedule('batched', '0 */6 * * *')
|
|
333
|
-
.then(fn('fetch-items', (ctx) => {
|
|
334
|
-
// Fetch 1000 inventory records
|
|
335
|
-
return fetchAllInventoryRecords(); // Returns array of 1000 items
|
|
336
|
-
}))
|
|
337
|
-
.unpack((items) => {
|
|
338
|
-
// Custom mapper: group into batches of 100
|
|
339
|
-
const batches = [];
|
|
340
|
-
for (let i = 0; i < items.length; i += 100) {
|
|
341
|
-
batches.push(items.slice(i, i + 100));
|
|
342
|
-
}
|
|
343
|
-
return batches; // Array of 10 batches
|
|
344
|
-
})
|
|
345
|
-
.parallel( // Process each batch concurrently
|
|
346
|
-
http('process-batch', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
347
|
-
const batch = ctx.data; // Array of 100 items
|
|
348
|
-
const client = await createClient(ctx);
|
|
349
|
-
|
|
350
|
-
const job = await client.createJob({ name: 'Batch Process' });
|
|
351
|
-
await client.sendBatch(job.id, {
|
|
352
|
-
action: 'UPSERT',
|
|
353
|
-
entityType: 'INVENTORY_POSITION',
|
|
354
|
-
entities: batch
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
return { batchSize: batch.length, jobId: job.id };
|
|
358
|
-
})
|
|
359
|
-
);
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
### Example 3: Parallel GraphQL Queries
|
|
363
|
-
|
|
364
|
-
Execute multiple independent GraphQL queries concurrently:
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
export const parallelQueries = http(
|
|
368
|
-
'multi-query',
|
|
369
|
-
{ connection: 'fluent_commerce' },
|
|
370
|
-
async (ctx) => {
|
|
371
|
-
return [
|
|
372
|
-
{ entity: 'products', query: '...' },
|
|
373
|
-
{ entity: 'locations', query: '...' },
|
|
374
|
-
{ entity: 'inventory', query: '...' }
|
|
375
|
-
];
|
|
376
|
-
}
|
|
377
|
-
)
|
|
378
|
-
.unpack()
|
|
379
|
-
.parallel(
|
|
380
|
-
http('execute-query', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
381
|
-
const { entity, query } = ctx.data;
|
|
382
|
-
const client = await createClient(ctx);
|
|
383
|
-
|
|
384
|
-
const result = await client.graphql({ query });
|
|
385
|
-
return { entity, data: result.data };
|
|
386
|
-
})
|
|
387
|
-
);
|
|
388
|
-
```
|
|
389
|
-
|
|
390
|
-
**Performance**:
|
|
391
|
-
- Sequential: 60s + 30s + 30s = 120s
|
|
392
|
-
- Parallel: max(60s, 30s, 30s) = 60s
|
|
393
|
-
- **2x speedup**
|
|
394
|
-
|
|
395
|
-
### Example 4: Serial Processing (Order Matters)
|
|
396
|
-
|
|
397
|
-
Process items sequentially when order is critical:
|
|
398
|
-
|
|
399
|
-
```typescript
|
|
400
|
-
export const serialProcessing = schedule('serial', '0 * * * *')
|
|
401
|
-
.then(fn('prepare-updates', (ctx) => {
|
|
402
|
-
return [
|
|
403
|
-
{ action: 'delete', id: '123' },
|
|
404
|
-
{ action: 'create', id: '123', data: {...} },
|
|
405
|
-
{ action: 'update', id: '123', field: 'status' }
|
|
406
|
-
];
|
|
407
|
-
}))
|
|
408
|
-
.unpack()
|
|
409
|
-
.serial( // Process sequentially (delete before create)
|
|
410
|
-
http('execute-action', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
411
|
-
const action = ctx.data;
|
|
412
|
-
const client = await createClient(ctx);
|
|
413
|
-
|
|
414
|
-
// Execute action based on type
|
|
415
|
-
return await executeAction(client, action);
|
|
416
|
-
})
|
|
417
|
-
);
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
---
|
|
421
|
-
|
|
422
|
-
## Performance Characteristics
|
|
423
|
-
|
|
424
|
-
### Memory Usage
|
|
425
|
-
|
|
426
|
-
| Array Size | Memory Impact | Recommendation |
|
|
427
|
-
|------------|---------------|----------------|
|
|
428
|
-
| 1-10 items | Negligible | ✅ Use parallel |
|
|
429
|
-
| 10-50 items | Low (~1-5MB) | ✅ Use parallel |
|
|
430
|
-
| 50-100 items | Moderate (~5-10MB) | ⚠️ Consider batching |
|
|
431
|
-
| 100-500 items | High (~10-50MB) | ❌ Use SDK Promise.allSettled with concurrency limit |
|
|
432
|
-
| 500+ items | Very High (>50MB) | ❌ Use sequential or chunked approach |
|
|
433
|
-
|
|
434
|
-
**Note**: Versori runtime has ~512MB memory limit (platform constraint, not SDK limitation).
|
|
435
|
-
|
|
436
|
-
### Execution Time
|
|
437
|
-
|
|
438
|
-
```
|
|
439
|
-
Parallel: T = max(T1, T2, ..., Tn) // Longest task
|
|
440
|
-
Serial: T = T1 + T2 + ... + Tn // Sum of all tasks
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
**When Parallel is Faster**:
|
|
444
|
-
- Independent tasks
|
|
445
|
-
- Similar execution times
|
|
446
|
-
- Network I/O bound operations
|
|
447
|
-
|
|
448
|
-
**When Serial is Better**:
|
|
449
|
-
- Dependent tasks
|
|
450
|
-
- Rate-limited APIs
|
|
451
|
-
- Memory constraints
|
|
452
|
-
- Progress tracking required
|
|
453
|
-
|
|
454
|
-
---
|
|
455
|
-
|
|
456
|
-
## Platform Constraints
|
|
457
|
-
|
|
458
|
-
### Timeout Limits
|
|
459
|
-
|
|
460
|
-
**⚠️ Important**: Timeout limits are enforced at the **Versori platform infrastructure level**, not in the `@versori/run` package code.
|
|
461
|
-
|
|
462
|
-
| Trigger Type | Platform Timeout | Source |
|
|
463
|
-
|--------------|------------------|--------|
|
|
464
|
-
| `http()` | Not explicitly documented | Versori platform |
|
|
465
|
-
| `webhook()` | Not explicitly documented | Versori platform |
|
|
466
|
-
| `schedule()` | Not explicitly documented | Versori platform |
|
|
467
|
-
|
|
468
|
-
**Recommended Safe Limits** (conservative estimates based on typical cloud function timeouts):
|
|
469
|
-
- `http()`: Assume 30-60 seconds
|
|
470
|
-
- `webhook()`: Assume 30-60 seconds
|
|
471
|
-
- `schedule()`: Assume 5-15 minutes
|
|
472
|
-
|
|
473
|
-
**How to Verify Your Limits**:
|
|
474
|
-
1. Check Versori platform documentation at https://docs.versori.com
|
|
475
|
-
2. Contact Versori support for your specific workspace limits
|
|
476
|
-
3. Test with long-running workflows to identify actual timeout
|
|
477
|
-
|
|
478
|
-
**Timeout Not Found in SDK Code**:
|
|
479
|
-
- Searched `@versori/run` package (v0.4.8) source code
|
|
480
|
-
- No hardcoded timeout constants found in:
|
|
481
|
-
- `http.js`, `webhook.js`, `schedule.js` compilers
|
|
482
|
-
- Interpreter implementations
|
|
483
|
-
- Task execution engines
|
|
484
|
-
- Timeouts are platform-enforced, not SDK-defined
|
|
485
|
-
|
|
486
|
-
### Concurrency Limits
|
|
487
|
-
|
|
488
|
-
| Method | Concurrency Control | Max Concurrent |
|
|
489
|
-
|--------|---------------------|----------------|
|
|
490
|
-
| `.parallel()` | None (all at once) | Unlimited |
|
|
491
|
-
| `.serial()` | 1 at a time | 1 |
|
|
492
|
-
| SDK `Promise.allSettled` | Configurable | 1-100 |
|
|
493
|
-
|
|
494
|
-
**Platform-Level Limits** (Versori infrastructure):
|
|
495
|
-
- ~10-50 concurrent HTTP connections per workflow (estimated)
|
|
496
|
-
- Memory: ~512MB per workflow execution (estimated)
|
|
497
|
-
- CPU: Shared among concurrent tasks
|
|
498
|
-
|
|
499
|
-
---
|
|
500
|
-
|
|
501
|
-
## Decision Matrix
|
|
502
|
-
|
|
503
|
-
### When to Use `.unpack().parallel()`
|
|
504
|
-
|
|
505
|
-
✅ **Use When**:
|
|
506
|
-
- 3-50 independent items to process
|
|
507
|
-
- Each item takes similar time (10-60s)
|
|
508
|
-
- Total estimated time < 4 minutes (safe buffer for platform timeout)
|
|
509
|
-
- Downstream APIs can handle concurrent requests
|
|
510
|
-
- All-or-nothing outcome is acceptable
|
|
511
|
-
- **Examples**: Multi-file SFTP ingestion, parallel GraphQL queries, multi-source data fetch
|
|
512
|
-
|
|
513
|
-
❌ **Don't Use When**:
|
|
514
|
-
- Need bounded concurrency (limit to 5-10 concurrent)
|
|
515
|
-
- Items have variable processing time (1s to 5min)
|
|
516
|
-
- Need partial success handling
|
|
517
|
-
- Downstream has strict rate limits
|
|
518
|
-
- Need custom retry logic per item
|
|
519
|
-
- **Alternative**: Use SDK `Promise.allSettled` with bounded concurrency
|
|
520
|
-
|
|
521
|
-
### When to Use `.unpack().serial()`
|
|
522
|
-
|
|
523
|
-
✅ **Use When**:
|
|
524
|
-
- Order of execution matters
|
|
525
|
-
- Items depend on previous items
|
|
526
|
-
- Rate-limited APIs (1 req/sec)
|
|
527
|
-
- Precise progress tracking needed
|
|
528
|
-
- **Examples**: Database migrations, sequential state updates, ordered batch operations
|
|
529
|
-
|
|
530
|
-
❌ **Don't Use When**:
|
|
531
|
-
- Items are independent
|
|
532
|
-
- Need speed over order
|
|
533
|
-
- Processing 100+ items (too slow)
|
|
534
|
-
- **Alternative**: Use `.parallel()` or chunked approach
|
|
535
|
-
|
|
536
|
-
### When to Use SDK Promise.allSettled
|
|
537
|
-
|
|
538
|
-
✅ **Use When**:
|
|
539
|
-
- Need bounded concurrency (e.g., 5-10 concurrent)
|
|
540
|
-
- Need per-item error handling
|
|
541
|
-
- Want partial success (commit what works)
|
|
542
|
-
- Have custom retry logic
|
|
543
|
-
- **Examples**: Batch API submissions, Event API calls (already in SDK templates)
|
|
544
|
-
|
|
545
|
-
**Current SDK Usage**:
|
|
546
|
-
- `BatchProcessorService`: Already uses `Promise.allSettled` with configurable concurrency (1-10)
|
|
547
|
-
- `EventSenderService`: Already uses `Promise.allSettled` for parallel event submission
|
|
548
|
-
- **No changes needed** - already optimal!
|
|
549
|
-
|
|
550
|
-
---
|
|
551
|
-
|
|
552
|
-
## Recommended Parallel Processing Patterns
|
|
553
|
-
|
|
554
|
-
### Pattern 1: Small, Reliable, All-or-Nothing (Use `.parallel()`)
|
|
555
|
-
|
|
556
|
-
```typescript
|
|
557
|
-
// ✅ Good use case: Fetching required entity types
|
|
558
|
-
export const fetchRequiredData = http(
|
|
559
|
-
'fetch-all',
|
|
560
|
-
{ connection: 'fluent_commerce' },
|
|
561
|
-
async (ctx) => {
|
|
562
|
-
return [
|
|
563
|
-
{ entity: 'PRODUCT', query: '...' },
|
|
564
|
-
{ entity: 'LOCATION', query: '...' },
|
|
565
|
-
{ entity: 'CATEGORY', query: '...' }
|
|
566
|
-
];
|
|
567
|
-
}
|
|
568
|
-
)
|
|
569
|
-
.unpack()
|
|
570
|
-
.parallel( // ✅ Okay here - all 3 must succeed
|
|
571
|
-
http('execute', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
572
|
-
const client = await createClient(ctx);
|
|
573
|
-
return await client.graphql({ query: ctx.data.query });
|
|
574
|
-
})
|
|
575
|
-
);
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
**When this fails:** You probably want the workflow to fail anyway since all entities are required.
|
|
579
|
-
|
|
580
|
-
---
|
|
581
|
-
|
|
582
|
-
### Pattern 2: Large, Unreliable, Partial Success (Use `Promise.allSettled`)
|
|
583
|
-
|
|
584
|
-
```typescript
|
|
585
|
-
// ✅ Better approach: Batch file processing
|
|
586
|
-
export const batchFileIngestion = schedule('ingest', '0 */6 * * *')
|
|
587
|
-
.then(
|
|
588
|
-
http('process-all', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
589
|
-
const sftp = new SftpDataSource(config, ctx.log);
|
|
590
|
-
const files = await sftp.listFiles('/incoming/');
|
|
591
|
-
|
|
592
|
-
// ✅ Use Promise.allSettled for fault tolerance
|
|
593
|
-
const results = await Promise.allSettled(
|
|
594
|
-
files.map(async (file) => {
|
|
595
|
-
try {
|
|
596
|
-
const content = await sftp.downloadFile(file.path);
|
|
597
|
-
const records = await parseXML(content);
|
|
598
|
-
|
|
599
|
-
const client = await createClient(ctx);
|
|
600
|
-
const job = await client.createJob({ name: `Process ${file.name}` });
|
|
601
|
-
await client.sendBatch(job.id, {
|
|
602
|
-
action: 'UPSERT',
|
|
603
|
-
entityType: 'INVENTORY_POSITION',
|
|
604
|
-
entities: records
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
return { success: true, file: file.name, count: records.length };
|
|
608
|
-
} catch (error) {
|
|
609
|
-
return { success: false, file: file.name, error: error.message };
|
|
610
|
-
}
|
|
611
|
-
})
|
|
612
|
-
);
|
|
613
|
-
|
|
614
|
-
const successes = results
|
|
615
|
-
.filter(r => r.status === 'fulfilled' && r.value.success)
|
|
616
|
-
.map(r => r.value);
|
|
617
|
-
|
|
618
|
-
const failures = results
|
|
619
|
-
.filter(r => r.status === 'rejected' || !r.value?.success);
|
|
620
|
-
|
|
621
|
-
// ✅ Partial success is valuable
|
|
622
|
-
ctx.log.info(`Processed ${successes.length}/${files.length} files`);
|
|
623
|
-
|
|
624
|
-
return { successes, failures };
|
|
625
|
-
})
|
|
626
|
-
);
|
|
627
|
-
```
|
|
628
|
-
|
|
629
|
-
**When this fails:** You still get partial results (processed 45/50 files successfully).
|
|
630
|
-
|
|
631
|
-
---
|
|
632
|
-
|
|
633
|
-
### Pattern 3: `.parallel()` with Safe Error Handling
|
|
634
|
-
|
|
635
|
-
```typescript
|
|
636
|
-
// ✅ If you MUST use .parallel(), wrap errors
|
|
637
|
-
export const safeParallel = schedule('process', '0 2 * * *')
|
|
638
|
-
.then(fn('fetch', () => ['file1.xml', 'file2.xml', 'file3.xml']))
|
|
639
|
-
.unpack()
|
|
640
|
-
.parallel(fn('process', async (ctx) => {
|
|
641
|
-
try {
|
|
642
|
-
const result = await processFile(ctx.data);
|
|
643
|
-
return { success: true, file: ctx.data, result };
|
|
644
|
-
} catch (error) {
|
|
645
|
-
// ✅ Return error object instead of throwing
|
|
646
|
-
return { success: false, file: ctx.data, error: error.message };
|
|
647
|
-
}
|
|
648
|
-
}))
|
|
649
|
-
.then(fn('handle-results', (ctx) => {
|
|
650
|
-
const successes = ctx.data.filter(r => r.success);
|
|
651
|
-
const failures = ctx.data.filter(r => !r.success);
|
|
652
|
-
|
|
653
|
-
if (failures.length > 0) {
|
|
654
|
-
ctx.log.error(`${failures.length} files failed`, failures);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
return { successes, failures };
|
|
658
|
-
}));
|
|
659
|
-
```
|
|
660
|
-
|
|
661
|
-
**Note:** This pattern requires careful error handling in EVERY parallel task. `Promise.allSettled` is simpler and more reliable.
|
|
662
|
-
|
|
663
|
-
---
|
|
664
|
-
|
|
665
|
-
## Compiler Registration
|
|
666
|
-
|
|
667
|
-
All task types are registered in the ObservableCompiler:
|
|
668
|
-
|
|
669
|
-
**Location**: `ObservableCompiler.js:40-46` in `@versori/run` package
|
|
670
|
-
|
|
671
|
-
```javascript
|
|
672
|
-
// Register all available compilers
|
|
673
|
-
this.registerTask(parallelCompiler);
|
|
674
|
-
this.registerTask(serialCompiler);
|
|
675
|
-
this.registerTask(catchCompiler);
|
|
676
|
-
this.registerTask(chainCompiler);
|
|
677
|
-
this.registerTask(fnCompiler);
|
|
678
|
-
this.registerTask(backgroundCompiler);
|
|
679
|
-
this.registerTask(unpackCompiler);
|
|
680
|
-
this.registerTask(httpCompiler);
|
|
681
|
-
```
|
|
682
|
-
|
|
683
|
-
---
|
|
684
|
-
|
|
685
|
-
## Summary
|
|
686
|
-
|
|
687
|
-
- ✅ `.unpack()` and `.parallel()` **are fully supported** in @versori/run v0.4.0+
|
|
688
|
-
- ✅ Verified from actual npm package source code
|
|
689
|
-
- ✅ Implemented using RxJS `mergeMap` for true parallel execution
|
|
690
|
-
- ✅ Maintains order in output array
|
|
691
|
-
- ⚠️ No built-in concurrency limits - processes all items simultaneously
|
|
692
|
-
- ⚠️ Platform timeout limits enforced by Versori infrastructure (not SDK)
|
|
693
|
-
- ⚠️ Best for 3-50 independent items with similar execution times
|
|
694
|
-
- ✅ For Batch/Event API: SDK's `Promise.allSettled` approach is already optimal
|
|
695
|
-
|
|
696
|
-
---
|
|
697
|
-
|
|
698
|
-
## Related Documentation
|
|
699
|
-
|
|
700
|
-
- [Module 4: Workflows](./modules/platforms-versori-04-workflows.md) - Core workflow patterns
|
|
701
|
-
- Versori Run SDK TypeScript Definitions - Available in `@versori/run` package at `node_modules/@versori/run/esm/src/dsl/Task.d.ts`
|
|
702
|
-
- SDK Batch Processing Service - See source at `src/services/orchestration/ingestion-service.ts`
|
|
703
|
-
|
|
704
|
-
---
|
|
705
|
-
|
|
706
|
-
**Last Verified**: 2025-01-04
|
|
707
|
-
**Package Version**: @versori/run@0.4.8
|
|
708
|
-
**Source**: npm registry + local node_modules inspection
|
|
1
|
+
# Versori Workflow Task Types - Complete Reference
|
|
2
|
+
|
|
3
|
+
**@versori/run Package Version**: v0.4.8 (verified from npm)
|
|
4
|
+
**SDK Compatibility**: Use latest @fluentcommerce/fc-connect-sdk
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Table of Contents
|
|
9
|
+
|
|
10
|
+
1. [Overview](#overview)
|
|
11
|
+
2. [Task Chaining Methods](#task-chaining-methods)
|
|
12
|
+
3. [Parallel Processing with `.unpack()`](#parallel-processing-with-unpack)
|
|
13
|
+
4. [Serial Processing](#serial-processing)
|
|
14
|
+
5. [Working Examples](#working-examples)
|
|
15
|
+
6. [Performance Characteristics](#performance-characteristics)
|
|
16
|
+
7. [Platform Constraints](#platform-constraints)
|
|
17
|
+
8. [Decision Matrix](#decision-matrix)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Overview
|
|
22
|
+
|
|
23
|
+
Versori's `@versori/run` package provides a fluent API for building workflows with support for parallel and serial array processing. All Task types (`fn`, `http`, `schedule`) support the full chain of methods including `.unpack()` and `.parallel()`.
|
|
24
|
+
|
|
25
|
+
### Core Task Methods
|
|
26
|
+
|
|
27
|
+
| Method | Returns | Purpose | Code Location |
|
|
28
|
+
|--------|---------|---------|---------------|
|
|
29
|
+
| `.then()` | `Task` | Chain next task | `Task.d.ts:20` |
|
|
30
|
+
| `.catch()` | `Task` | Handle errors | `Task.d.ts:29` |
|
|
31
|
+
| `.background()` | `Task` | Run in background | `Task.d.ts:34` |
|
|
32
|
+
| `.unpack()` | `ArrayTask` | Split array into elements | `Task.d.ts:35-36` |
|
|
33
|
+
| `.clone()` | `Task` | Clone task | `Task.d.ts:40` |
|
|
34
|
+
|
|
35
|
+
### ArrayTask Methods (after unpack())
|
|
36
|
+
|
|
37
|
+
| Method | Returns | Purpose | Code Location |
|
|
38
|
+
|--------|---------|---------|---------------|
|
|
39
|
+
| `.parallel()` | `Task` | Process array elements in parallel | `Task.d.ts:59` |
|
|
40
|
+
| `.serial()` | `Task` | Process array elements sequentially | `Task.d.ts:67` |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Task Chaining Methods
|
|
45
|
+
|
|
46
|
+
### 1. `.then<NextOut>(task)` → `Task<In, NextOut>`
|
|
47
|
+
|
|
48
|
+
Chain the next task after current task completes.
|
|
49
|
+
|
|
50
|
+
**Implementation**: `Task.d.ts:20` in `@versori/run` package
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
schedule('example', '0 * * * *')
|
|
54
|
+
.then(fn('step1', (ctx) => ({ result: 'data' })))
|
|
55
|
+
.then(fn('step2', (ctx) => {
|
|
56
|
+
console.log(ctx.data.result); // 'data'
|
|
57
|
+
return { next: 'value' };
|
|
58
|
+
}));
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2. `.catch<NextOut>(task)` → `Task<In, NextOut>`
|
|
62
|
+
|
|
63
|
+
Handle errors from previous task. Workflow continues after catch.
|
|
64
|
+
|
|
65
|
+
**Implementation**: `Task.d.ts:29` in `@versori/run` package
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
schedule('example', '0 * * * *')
|
|
69
|
+
.then(fn('may-fail', (ctx) => {
|
|
70
|
+
throw new Error('Something failed');
|
|
71
|
+
}))
|
|
72
|
+
.catch(fn('handle-error', (ctx) => {
|
|
73
|
+
console.error(ctx.data); // Error object
|
|
74
|
+
return { recovered: true };
|
|
75
|
+
}));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 3. `.background()` → `Task<In, void>`
|
|
79
|
+
|
|
80
|
+
Run task in background. Next task receives `void` as input.
|
|
81
|
+
|
|
82
|
+
**Implementation**: `Task.d.ts:34` in `@versori/run` package
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
schedule('example', '0 * * * *')
|
|
86
|
+
.then(fn('long-running', (ctx) => {
|
|
87
|
+
// Long operation
|
|
88
|
+
}))
|
|
89
|
+
.background() // Doesn't wait for completion
|
|
90
|
+
.then(fn('continues-immediately', (ctx) => {
|
|
91
|
+
// ctx.data is void
|
|
92
|
+
}));
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Parallel Processing with unpack()
|
|
98
|
+
|
|
99
|
+
### `.unpack()` Method
|
|
100
|
+
|
|
101
|
+
Splits an array output into individual elements, returning an `ArrayTask` that provides `.parallel()` and `.serial()` methods.
|
|
102
|
+
|
|
103
|
+
**Signatures**:
|
|
104
|
+
```typescript
|
|
105
|
+
// Auto-unpack array
|
|
106
|
+
unpack<NextOut = Out extends Array<infer Elem> ? Elem : Out>(): ArrayTask<In, NextOut>
|
|
107
|
+
|
|
108
|
+
// Custom mapper
|
|
109
|
+
unpack<NextOut>(mapper: (data: Out) => NextOut[]): ArrayTask<In, NextOut>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Implementation Locations**:
|
|
113
|
+
- Interface: `Task.d.ts:35-36`
|
|
114
|
+
- FnTask: `FnTask.js:52-57`
|
|
115
|
+
- HttpTask: `HttpTask.js:70-75`
|
|
116
|
+
- UnpackTask class: `UnpackTask.js`
|
|
117
|
+
- Compiler: `unpack.js:21-30`
|
|
118
|
+
|
|
119
|
+
All files are in the `@versori/run` package under `node_modules/@versori/run/esm/src/`
|
|
120
|
+
|
|
121
|
+
### `.parallel()` Method
|
|
122
|
+
|
|
123
|
+
Process each array element concurrently using RxJS `mergeMap`.
|
|
124
|
+
|
|
125
|
+
**Signature**:
|
|
126
|
+
```typescript
|
|
127
|
+
parallel<NextOut>(task: Taskable<OutElem, NextOut, number>): Task<In, NextOut[]>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Implementation Locations** in `@versori/run` package:
|
|
131
|
+
- Interface: `Task.d.ts:59`
|
|
132
|
+
- UnpackTask: `UnpackTask.js:44-46`
|
|
133
|
+
- ParallelTask class: `ParallelTask.js:25-47`
|
|
134
|
+
- Compiler: `parallel.js:15-27`
|
|
135
|
+
|
|
136
|
+
**Key Characteristics**:
|
|
137
|
+
- ✅ **Maintains order**: Results are sorted by original index
|
|
138
|
+
- ✅ **Type-safe**: Full TypeScript support with generics
|
|
139
|
+
- ✅ **No concurrency limit**: Processes all elements simultaneously
|
|
140
|
+
- ⚠️ **Memory usage**: All results held in memory
|
|
141
|
+
- ⚠️ **Error handling**: One failure stops entire workflow
|
|
142
|
+
- ⚠️ **NOT fault-tolerant**: If any task fails, **all results are lost** (no partial results)
|
|
143
|
+
- ⚠️ **NOT ACID compliant**: No atomicity guarantees, no rollback mechanism
|
|
144
|
+
- ⚠️ **Shared timeout**: All parallel tasks share the same workflow timeout (30s/5min)
|
|
145
|
+
|
|
146
|
+
### ⚠️ CRITICAL: Fault Tolerance Limitations
|
|
147
|
+
|
|
148
|
+
**Problem**: `.parallel()` uses RxJS `mergeMap` + `toArray()` which stops on first error. This means:
|
|
149
|
+
|
|
150
|
+
1. **One failure stops everything**: If any parallel task throws an error, the entire workflow fails
|
|
151
|
+
2. **No partial results**: You won't receive successful results even if most tasks succeeded
|
|
152
|
+
3. **No error isolation**: Failed tasks prevent successful tasks from completing
|
|
153
|
+
|
|
154
|
+
**Example of the problem**:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
schedule('process-files', '0 2 * * *')
|
|
158
|
+
.then(fn('fetch-files', (ctx) => ['file1.xml', 'file2.xml', 'file3.xml']))
|
|
159
|
+
.unpack()
|
|
160
|
+
.parallel(fn('process-file', async (ctx) => {
|
|
161
|
+
// ❌ If file2.xml fails here...
|
|
162
|
+
return await processFile(ctx.data);
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
// Result:
|
|
166
|
+
// ✅ file1.xml might complete
|
|
167
|
+
// ❌ file2.xml fails → ENTIRE WORKFLOW FAILS
|
|
168
|
+
// ❌ file3.xml NEVER RUNS (or gets cancelled)
|
|
169
|
+
// ❌ No partial results returned
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Why this happens**: The RxJS `toArray()` operator never completes if the stream errors before all items are processed.
|
|
173
|
+
|
|
174
|
+
### ✅ Recommended: Use `Promise.allSettled()` for Fault Tolerance
|
|
175
|
+
|
|
176
|
+
For **production workloads** where failures are expected, use `Promise.allSettled()` inside a `fn()` task:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
schedule('process-files', '0 2 * * *')
|
|
180
|
+
.then(fn('process-all-files', async (ctx) => {
|
|
181
|
+
const files = ['file1.xml', 'file2.xml', 'file3.xml'];
|
|
182
|
+
|
|
183
|
+
// ✅ Fault-tolerant: Continues even if some fail
|
|
184
|
+
const results = await Promise.allSettled(
|
|
185
|
+
files.map(file => processFile(file))
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
// Process results
|
|
189
|
+
const successes = results
|
|
190
|
+
.filter(r => r.status === 'fulfilled')
|
|
191
|
+
.map(r => r.value);
|
|
192
|
+
|
|
193
|
+
const failures = results
|
|
194
|
+
.filter(r => r.status === 'rejected')
|
|
195
|
+
.map(r => ({ file: r.reason.file, error: r.reason.message }));
|
|
196
|
+
|
|
197
|
+
ctx.log.info(`Processed ${successes.length} files, ${failures.length} failed`);
|
|
198
|
+
|
|
199
|
+
return { successes, failures };
|
|
200
|
+
}));
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Comparison**:
|
|
204
|
+
|
|
205
|
+
| Feature | `.unpack().parallel()` | `Promise.allSettled()` |
|
|
206
|
+
|---------|------------------------|------------------------|
|
|
207
|
+
| Fault tolerance | ❌ Fails on first error | ✅ Continues on errors |
|
|
208
|
+
| Partial results | ❌ No results if any fail | ✅ Returns all results |
|
|
209
|
+
| Error isolation | ❌ No isolation | ✅ Complete isolation |
|
|
210
|
+
| Best for | All-or-nothing workflows | Real-world with failures |
|
|
211
|
+
|
|
212
|
+
See [Module 4: Workflows](./modules/platforms-versori-04-workflows.md#-critical-parallel-processing-with-unpack-and-parallel) for detailed guidance.
|
|
213
|
+
|
|
214
|
+
### Execution Engine
|
|
215
|
+
|
|
216
|
+
The parallel compiler uses RxJS operators:
|
|
217
|
+
|
|
218
|
+
```javascript
|
|
219
|
+
// From parallel.js:15-27
|
|
220
|
+
function compileParallel(ctx, task) {
|
|
221
|
+
const baseOperator = ctx.compiler.compileTask(ctx, task._base);
|
|
222
|
+
const eachOperator = ctx.compiler.compileTask(ctx, task._each);
|
|
223
|
+
|
|
224
|
+
return (src) => src.pipe(
|
|
225
|
+
baseOperator,
|
|
226
|
+
mergeMap((ctx) => {
|
|
227
|
+
return from(ctx.data).pipe(
|
|
228
|
+
map((data, idx) => ctx.withData(data).setIndex(idx)),
|
|
229
|
+
// Process items in parallel using mergeMap
|
|
230
|
+
mergeMap((item) => eachOperator(of(item)).pipe(
|
|
231
|
+
map((result) => result.setIndex(item.idx))
|
|
232
|
+
)),
|
|
233
|
+
toArray(),
|
|
234
|
+
map((results) => {
|
|
235
|
+
// Sort by original index to maintain order
|
|
236
|
+
results.sort((a, b) => a.idx - b.idx);
|
|
237
|
+
return ctx.withData(results.map((r) => r.data));
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
})
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Serial Processing
|
|
248
|
+
|
|
249
|
+
### `.serial()` Method
|
|
250
|
+
|
|
251
|
+
Process each array element sequentially (one after another).
|
|
252
|
+
|
|
253
|
+
**Signature**:
|
|
254
|
+
```typescript
|
|
255
|
+
serial<NextOut>(task: Taskable<OutElem, NextOut, number>): Task<In, NextOut[]>
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Implementation** in `@versori/run` package:
|
|
259
|
+
- Interface: `Task.d.ts:67`
|
|
260
|
+
- UnpackTask: `UnpackTask.js:48-50`
|
|
261
|
+
- SerialTask class: `SerialTask.js`
|
|
262
|
+
- Compiler: `serial.js`
|
|
263
|
+
|
|
264
|
+
**Use When**:
|
|
265
|
+
- Order of execution matters
|
|
266
|
+
- Items depend on previous items
|
|
267
|
+
- Rate limiting required
|
|
268
|
+
- Precise progress tracking needed
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## Working Examples
|
|
273
|
+
|
|
274
|
+
### Example 1: Parallel File Processing
|
|
275
|
+
|
|
276
|
+
Process multiple SFTP XML files concurrently:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { schedule, fn, http } from '@versori/run';
|
|
280
|
+
import { createClient, SftpDataSource } from '@fluentcommerce/fc-connect-sdk';
|
|
281
|
+
|
|
282
|
+
export const parallelFileProcessing = schedule('parallel-files', '0 */6 * * *')
|
|
283
|
+
.then(fn('list-files', async (ctx) => {
|
|
284
|
+
const sftp = new SftpDataSource(sftpConfig, ctx.log);
|
|
285
|
+
await sftp.connect();
|
|
286
|
+
|
|
287
|
+
const files = await sftp.listFiles({
|
|
288
|
+
remotePath: '/incoming/inventory/',
|
|
289
|
+
filePattern: '.xml'
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
await sftp.disconnect();
|
|
293
|
+
|
|
294
|
+
return files; // Array of file metadata
|
|
295
|
+
}))
|
|
296
|
+
.unpack() // Split array into individual files
|
|
297
|
+
.parallel( // Process each file concurrently
|
|
298
|
+
http('process-file', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
299
|
+
const file = ctx.data; // Single file metadata
|
|
300
|
+
const client = await createClient(ctx);
|
|
301
|
+
|
|
302
|
+
// Download and process file
|
|
303
|
+
const sftp = new SftpDataSource(sftpConfig, ctx.log);
|
|
304
|
+
await sftp.connect();
|
|
305
|
+
const content = await sftp.downloadFile(file.path);
|
|
306
|
+
await sftp.disconnect();
|
|
307
|
+
|
|
308
|
+
// Parse, map, and send to Fluent
|
|
309
|
+
const records = await parseAndMap(content);
|
|
310
|
+
const job = await client.createJob({ name: `Process ${file.name}` });
|
|
311
|
+
await client.sendBatch(job.id, {
|
|
312
|
+
action: 'UPSERT',
|
|
313
|
+
entityType: 'INVENTORY_POSITION',
|
|
314
|
+
entities: records
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
return { file: file.name, jobId: job.id, recordCount: records.length };
|
|
318
|
+
})
|
|
319
|
+
);
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
**Performance**:
|
|
323
|
+
- 10 files × 30s each = 300s (sequential)
|
|
324
|
+
- 10 files processed simultaneously = 30s (parallel)
|
|
325
|
+
- **10x speedup**
|
|
326
|
+
|
|
327
|
+
### Example 2: Custom Batching with Mapper
|
|
328
|
+
|
|
329
|
+
Group items into batches, then process batches in parallel:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
export const batchedParallelProcessing = schedule('batched', '0 */6 * * *')
|
|
333
|
+
.then(fn('fetch-items', (ctx) => {
|
|
334
|
+
// Fetch 1000 inventory records
|
|
335
|
+
return fetchAllInventoryRecords(); // Returns array of 1000 items
|
|
336
|
+
}))
|
|
337
|
+
.unpack((items) => {
|
|
338
|
+
// Custom mapper: group into batches of 100
|
|
339
|
+
const batches = [];
|
|
340
|
+
for (let i = 0; i < items.length; i += 100) {
|
|
341
|
+
batches.push(items.slice(i, i + 100));
|
|
342
|
+
}
|
|
343
|
+
return batches; // Array of 10 batches
|
|
344
|
+
})
|
|
345
|
+
.parallel( // Process each batch concurrently
|
|
346
|
+
http('process-batch', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
347
|
+
const batch = ctx.data; // Array of 100 items
|
|
348
|
+
const client = await createClient(ctx);
|
|
349
|
+
|
|
350
|
+
const job = await client.createJob({ name: 'Batch Process' });
|
|
351
|
+
await client.sendBatch(job.id, {
|
|
352
|
+
action: 'UPSERT',
|
|
353
|
+
entityType: 'INVENTORY_POSITION',
|
|
354
|
+
entities: batch
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
return { batchSize: batch.length, jobId: job.id };
|
|
358
|
+
})
|
|
359
|
+
);
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Example 3: Parallel GraphQL Queries
|
|
363
|
+
|
|
364
|
+
Execute multiple independent GraphQL queries concurrently:
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
export const parallelQueries = http(
|
|
368
|
+
'multi-query',
|
|
369
|
+
{ connection: 'fluent_commerce' },
|
|
370
|
+
async (ctx) => {
|
|
371
|
+
return [
|
|
372
|
+
{ entity: 'products', query: '...' },
|
|
373
|
+
{ entity: 'locations', query: '...' },
|
|
374
|
+
{ entity: 'inventory', query: '...' }
|
|
375
|
+
];
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
.unpack()
|
|
379
|
+
.parallel(
|
|
380
|
+
http('execute-query', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
381
|
+
const { entity, query } = ctx.data;
|
|
382
|
+
const client = await createClient(ctx);
|
|
383
|
+
|
|
384
|
+
const result = await client.graphql({ query });
|
|
385
|
+
return { entity, data: result.data };
|
|
386
|
+
})
|
|
387
|
+
);
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Performance**:
|
|
391
|
+
- Sequential: 60s + 30s + 30s = 120s
|
|
392
|
+
- Parallel: max(60s, 30s, 30s) = 60s
|
|
393
|
+
- **2x speedup**
|
|
394
|
+
|
|
395
|
+
### Example 4: Serial Processing (Order Matters)
|
|
396
|
+
|
|
397
|
+
Process items sequentially when order is critical:
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
export const serialProcessing = schedule('serial', '0 * * * *')
|
|
401
|
+
.then(fn('prepare-updates', (ctx) => {
|
|
402
|
+
return [
|
|
403
|
+
{ action: 'delete', id: '123' },
|
|
404
|
+
{ action: 'create', id: '123', data: {...} },
|
|
405
|
+
{ action: 'update', id: '123', field: 'status' }
|
|
406
|
+
];
|
|
407
|
+
}))
|
|
408
|
+
.unpack()
|
|
409
|
+
.serial( // Process sequentially (delete before create)
|
|
410
|
+
http('execute-action', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
411
|
+
const action = ctx.data;
|
|
412
|
+
const client = await createClient(ctx);
|
|
413
|
+
|
|
414
|
+
// Execute action based on type
|
|
415
|
+
return await executeAction(client, action);
|
|
416
|
+
})
|
|
417
|
+
);
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Performance Characteristics
|
|
423
|
+
|
|
424
|
+
### Memory Usage
|
|
425
|
+
|
|
426
|
+
| Array Size | Memory Impact | Recommendation |
|
|
427
|
+
|------------|---------------|----------------|
|
|
428
|
+
| 1-10 items | Negligible | ✅ Use parallel |
|
|
429
|
+
| 10-50 items | Low (~1-5MB) | ✅ Use parallel |
|
|
430
|
+
| 50-100 items | Moderate (~5-10MB) | ⚠️ Consider batching |
|
|
431
|
+
| 100-500 items | High (~10-50MB) | ❌ Use SDK Promise.allSettled with concurrency limit |
|
|
432
|
+
| 500+ items | Very High (>50MB) | ❌ Use sequential or chunked approach |
|
|
433
|
+
|
|
434
|
+
**Note**: Versori runtime has ~512MB memory limit (platform constraint, not SDK limitation).
|
|
435
|
+
|
|
436
|
+
### Execution Time
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
Parallel: T = max(T1, T2, ..., Tn) // Longest task
|
|
440
|
+
Serial: T = T1 + T2 + ... + Tn // Sum of all tasks
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**When Parallel is Faster**:
|
|
444
|
+
- Independent tasks
|
|
445
|
+
- Similar execution times
|
|
446
|
+
- Network I/O bound operations
|
|
447
|
+
|
|
448
|
+
**When Serial is Better**:
|
|
449
|
+
- Dependent tasks
|
|
450
|
+
- Rate-limited APIs
|
|
451
|
+
- Memory constraints
|
|
452
|
+
- Progress tracking required
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
## Platform Constraints
|
|
457
|
+
|
|
458
|
+
### Timeout Limits
|
|
459
|
+
|
|
460
|
+
**⚠️ Important**: Timeout limits are enforced at the **Versori platform infrastructure level**, not in the `@versori/run` package code.
|
|
461
|
+
|
|
462
|
+
| Trigger Type | Platform Timeout | Source |
|
|
463
|
+
|--------------|------------------|--------|
|
|
464
|
+
| `http()` | Not explicitly documented | Versori platform |
|
|
465
|
+
| `webhook()` | Not explicitly documented | Versori platform |
|
|
466
|
+
| `schedule()` | Not explicitly documented | Versori platform |
|
|
467
|
+
|
|
468
|
+
**Recommended Safe Limits** (conservative estimates based on typical cloud function timeouts):
|
|
469
|
+
- `http()`: Assume 30-60 seconds
|
|
470
|
+
- `webhook()`: Assume 30-60 seconds
|
|
471
|
+
- `schedule()`: Assume 5-15 minutes
|
|
472
|
+
|
|
473
|
+
**How to Verify Your Limits**:
|
|
474
|
+
1. Check Versori platform documentation at https://docs.versori.com
|
|
475
|
+
2. Contact Versori support for your specific workspace limits
|
|
476
|
+
3. Test with long-running workflows to identify actual timeout
|
|
477
|
+
|
|
478
|
+
**Timeout Not Found in SDK Code**:
|
|
479
|
+
- Searched `@versori/run` package (v0.4.8) source code
|
|
480
|
+
- No hardcoded timeout constants found in:
|
|
481
|
+
- `http.js`, `webhook.js`, `schedule.js` compilers
|
|
482
|
+
- Interpreter implementations
|
|
483
|
+
- Task execution engines
|
|
484
|
+
- Timeouts are platform-enforced, not SDK-defined
|
|
485
|
+
|
|
486
|
+
### Concurrency Limits
|
|
487
|
+
|
|
488
|
+
| Method | Concurrency Control | Max Concurrent |
|
|
489
|
+
|--------|---------------------|----------------|
|
|
490
|
+
| `.parallel()` | None (all at once) | Unlimited |
|
|
491
|
+
| `.serial()` | 1 at a time | 1 |
|
|
492
|
+
| SDK `Promise.allSettled` | Configurable | 1-100 |
|
|
493
|
+
|
|
494
|
+
**Platform-Level Limits** (Versori infrastructure):
|
|
495
|
+
- ~10-50 concurrent HTTP connections per workflow (estimated)
|
|
496
|
+
- Memory: ~512MB per workflow execution (estimated)
|
|
497
|
+
- CPU: Shared among concurrent tasks
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## Decision Matrix
|
|
502
|
+
|
|
503
|
+
### When to Use `.unpack().parallel()`
|
|
504
|
+
|
|
505
|
+
✅ **Use When**:
|
|
506
|
+
- 3-50 independent items to process
|
|
507
|
+
- Each item takes similar time (10-60s)
|
|
508
|
+
- Total estimated time < 4 minutes (safe buffer for platform timeout)
|
|
509
|
+
- Downstream APIs can handle concurrent requests
|
|
510
|
+
- All-or-nothing outcome is acceptable
|
|
511
|
+
- **Examples**: Multi-file SFTP ingestion, parallel GraphQL queries, multi-source data fetch
|
|
512
|
+
|
|
513
|
+
❌ **Don't Use When**:
|
|
514
|
+
- Need bounded concurrency (limit to 5-10 concurrent)
|
|
515
|
+
- Items have variable processing time (1s to 5min)
|
|
516
|
+
- Need partial success handling
|
|
517
|
+
- Downstream has strict rate limits
|
|
518
|
+
- Need custom retry logic per item
|
|
519
|
+
- **Alternative**: Use SDK `Promise.allSettled` with bounded concurrency
|
|
520
|
+
|
|
521
|
+
### When to Use `.unpack().serial()`
|
|
522
|
+
|
|
523
|
+
✅ **Use When**:
|
|
524
|
+
- Order of execution matters
|
|
525
|
+
- Items depend on previous items
|
|
526
|
+
- Rate-limited APIs (1 req/sec)
|
|
527
|
+
- Precise progress tracking needed
|
|
528
|
+
- **Examples**: Database migrations, sequential state updates, ordered batch operations
|
|
529
|
+
|
|
530
|
+
❌ **Don't Use When**:
|
|
531
|
+
- Items are independent
|
|
532
|
+
- Need speed over order
|
|
533
|
+
- Processing 100+ items (too slow)
|
|
534
|
+
- **Alternative**: Use `.parallel()` or chunked approach
|
|
535
|
+
|
|
536
|
+
### When to Use SDK Promise.allSettled
|
|
537
|
+
|
|
538
|
+
✅ **Use When**:
|
|
539
|
+
- Need bounded concurrency (e.g., 5-10 concurrent)
|
|
540
|
+
- Need per-item error handling
|
|
541
|
+
- Want partial success (commit what works)
|
|
542
|
+
- Have custom retry logic
|
|
543
|
+
- **Examples**: Batch API submissions, Event API calls (already in SDK templates)
|
|
544
|
+
|
|
545
|
+
**Current SDK Usage**:
|
|
546
|
+
- `BatchProcessorService`: Already uses `Promise.allSettled` with configurable concurrency (1-10)
|
|
547
|
+
- `EventSenderService`: Already uses `Promise.allSettled` for parallel event submission
|
|
548
|
+
- **No changes needed** - already optimal!
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## Recommended Parallel Processing Patterns
|
|
553
|
+
|
|
554
|
+
### Pattern 1: Small, Reliable, All-or-Nothing (Use `.parallel()`)
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
// ✅ Good use case: Fetching required entity types
|
|
558
|
+
export const fetchRequiredData = http(
|
|
559
|
+
'fetch-all',
|
|
560
|
+
{ connection: 'fluent_commerce' },
|
|
561
|
+
async (ctx) => {
|
|
562
|
+
return [
|
|
563
|
+
{ entity: 'PRODUCT', query: '...' },
|
|
564
|
+
{ entity: 'LOCATION', query: '...' },
|
|
565
|
+
{ entity: 'CATEGORY', query: '...' }
|
|
566
|
+
];
|
|
567
|
+
}
|
|
568
|
+
)
|
|
569
|
+
.unpack()
|
|
570
|
+
.parallel( // ✅ Okay here - all 3 must succeed
|
|
571
|
+
http('execute', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
572
|
+
const client = await createClient(ctx);
|
|
573
|
+
return await client.graphql({ query: ctx.data.query });
|
|
574
|
+
})
|
|
575
|
+
);
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**When this fails:** You probably want the workflow to fail anyway since all entities are required.
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
### Pattern 2: Large, Unreliable, Partial Success (Use `Promise.allSettled`)
|
|
583
|
+
|
|
584
|
+
```typescript
|
|
585
|
+
// ✅ Better approach: Batch file processing
|
|
586
|
+
export const batchFileIngestion = schedule('ingest', '0 */6 * * *')
|
|
587
|
+
.then(
|
|
588
|
+
http('process-all', { connection: 'fluent_commerce' }, async (ctx) => {
|
|
589
|
+
const sftp = new SftpDataSource(config, ctx.log);
|
|
590
|
+
const files = await sftp.listFiles('/incoming/');
|
|
591
|
+
|
|
592
|
+
// ✅ Use Promise.allSettled for fault tolerance
|
|
593
|
+
const results = await Promise.allSettled(
|
|
594
|
+
files.map(async (file) => {
|
|
595
|
+
try {
|
|
596
|
+
const content = await sftp.downloadFile(file.path);
|
|
597
|
+
const records = await parseXML(content);
|
|
598
|
+
|
|
599
|
+
const client = await createClient(ctx);
|
|
600
|
+
const job = await client.createJob({ name: `Process ${file.name}` });
|
|
601
|
+
await client.sendBatch(job.id, {
|
|
602
|
+
action: 'UPSERT',
|
|
603
|
+
entityType: 'INVENTORY_POSITION',
|
|
604
|
+
entities: records
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
return { success: true, file: file.name, count: records.length };
|
|
608
|
+
} catch (error) {
|
|
609
|
+
return { success: false, file: file.name, error: error.message };
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
const successes = results
|
|
615
|
+
.filter(r => r.status === 'fulfilled' && r.value.success)
|
|
616
|
+
.map(r => r.value);
|
|
617
|
+
|
|
618
|
+
const failures = results
|
|
619
|
+
.filter(r => r.status === 'rejected' || !r.value?.success);
|
|
620
|
+
|
|
621
|
+
// ✅ Partial success is valuable
|
|
622
|
+
ctx.log.info(`Processed ${successes.length}/${files.length} files`);
|
|
623
|
+
|
|
624
|
+
return { successes, failures };
|
|
625
|
+
})
|
|
626
|
+
);
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
**When this fails:** You still get partial results (processed 45/50 files successfully).
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
### Pattern 3: `.parallel()` with Safe Error Handling
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
// ✅ If you MUST use .parallel(), wrap errors
|
|
637
|
+
export const safeParallel = schedule('process', '0 2 * * *')
|
|
638
|
+
.then(fn('fetch', () => ['file1.xml', 'file2.xml', 'file3.xml']))
|
|
639
|
+
.unpack()
|
|
640
|
+
.parallel(fn('process', async (ctx) => {
|
|
641
|
+
try {
|
|
642
|
+
const result = await processFile(ctx.data);
|
|
643
|
+
return { success: true, file: ctx.data, result };
|
|
644
|
+
} catch (error) {
|
|
645
|
+
// ✅ Return error object instead of throwing
|
|
646
|
+
return { success: false, file: ctx.data, error: error.message };
|
|
647
|
+
}
|
|
648
|
+
}))
|
|
649
|
+
.then(fn('handle-results', (ctx) => {
|
|
650
|
+
const successes = ctx.data.filter(r => r.success);
|
|
651
|
+
const failures = ctx.data.filter(r => !r.success);
|
|
652
|
+
|
|
653
|
+
if (failures.length > 0) {
|
|
654
|
+
ctx.log.error(`${failures.length} files failed`, failures);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
return { successes, failures };
|
|
658
|
+
}));
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Note:** This pattern requires careful error handling in EVERY parallel task. `Promise.allSettled` is simpler and more reliable.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## Compiler Registration
|
|
666
|
+
|
|
667
|
+
All task types are registered in the ObservableCompiler:
|
|
668
|
+
|
|
669
|
+
**Location**: `ObservableCompiler.js:40-46` in `@versori/run` package
|
|
670
|
+
|
|
671
|
+
```javascript
|
|
672
|
+
// Register all available compilers
|
|
673
|
+
this.registerTask(parallelCompiler);
|
|
674
|
+
this.registerTask(serialCompiler);
|
|
675
|
+
this.registerTask(catchCompiler);
|
|
676
|
+
this.registerTask(chainCompiler);
|
|
677
|
+
this.registerTask(fnCompiler);
|
|
678
|
+
this.registerTask(backgroundCompiler);
|
|
679
|
+
this.registerTask(unpackCompiler);
|
|
680
|
+
this.registerTask(httpCompiler);
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## Summary
|
|
686
|
+
|
|
687
|
+
- ✅ `.unpack()` and `.parallel()` **are fully supported** in @versori/run v0.4.0+
|
|
688
|
+
- ✅ Verified from actual npm package source code
|
|
689
|
+
- ✅ Implemented using RxJS `mergeMap` for true parallel execution
|
|
690
|
+
- ✅ Maintains order in output array
|
|
691
|
+
- ⚠️ No built-in concurrency limits - processes all items simultaneously
|
|
692
|
+
- ⚠️ Platform timeout limits enforced by Versori infrastructure (not SDK)
|
|
693
|
+
- ⚠️ Best for 3-50 independent items with similar execution times
|
|
694
|
+
- ✅ For Batch/Event API: SDK's `Promise.allSettled` approach is already optimal
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
## Related Documentation
|
|
699
|
+
|
|
700
|
+
- [Module 4: Workflows](./modules/platforms-versori-04-workflows.md) - Core workflow patterns
|
|
701
|
+
- Versori Run SDK TypeScript Definitions - Available in `@versori/run` package at `node_modules/@versori/run/esm/src/dsl/Task.d.ts`
|
|
702
|
+
- SDK Batch Processing Service - See source at `src/services/orchestration/ingestion-service.ts`
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
**Last Verified**: 2025-01-04
|
|
707
|
+
**Package Version**: @versori/run@0.4.8
|
|
708
|
+
**Source**: npm registry + local node_modules inspection
|