@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,627 +1,627 @@
|
|
|
1
|
-
# JobTracker
|
|
2
|
-
|
|
3
|
-
**Level:** Advanced
|
|
4
|
-
**Category:** Production Services
|
|
5
|
-
**Purpose:** Track job lifecycle and status across workflows
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
`JobTracker` provides standardized job status tracking for Fluent Commerce integrations. It manages job lifecycle from creation through completion or failure, with automatic timestamp tracking and TTL support for cleanup.
|
|
10
|
-
|
|
11
|
-
## Use Cases
|
|
12
|
-
|
|
13
|
-
- ✅ Monitor scheduled workflow progress
|
|
14
|
-
- ✅ Track webhook-triggered operations
|
|
15
|
-
- ✅ Implement job retry logic
|
|
16
|
-
- ✅ Display job status in dashboards
|
|
17
|
-
- ✅ Debug failed jobs in production
|
|
18
|
-
- ✅ Track processing stages (extraction → transformation → ingestion)
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
import { JobTracker, VersoriKVAdapter } from '@fluentcommerce/fc-connect-sdk';
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Basic Usage
|
|
31
|
-
|
|
32
|
-
### Create and Track a Job
|
|
33
|
-
|
|
34
|
-
```typescript
|
|
35
|
-
import { JobTracker, VersoriKVAdapter } from '@fluentcommerce/fc-connect-sdk';
|
|
36
|
-
|
|
37
|
-
// Initialize tracker
|
|
38
|
-
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
39
|
-
const tracker = new JobTracker(kv, logger);
|
|
40
|
-
|
|
41
|
-
// Create job
|
|
42
|
-
const jobId = `scheduled_${Date.now()}`;
|
|
43
|
-
await tracker.createJob(jobId, {
|
|
44
|
-
triggeredBy: 'schedule',
|
|
45
|
-
stage: 'initialization',
|
|
46
|
-
details: {
|
|
47
|
-
catalogueRef: 'DEFAULT:1',
|
|
48
|
-
workflow: 'inventory-sync'
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Update as processing
|
|
53
|
-
await tracker.updateJob(jobId, {
|
|
54
|
-
status: 'processing',
|
|
55
|
-
stage: 'extraction',
|
|
56
|
-
message: 'Extracting inventory positions'
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Update stage
|
|
60
|
-
await tracker.updateJob(jobId, {
|
|
61
|
-
stage: 'transformation',
|
|
62
|
-
message: 'Transforming 1000 records'
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Mark complete
|
|
66
|
-
await tracker.markCompleted(jobId, {
|
|
67
|
-
recordCount: 1000,
|
|
68
|
-
fileName: 'inventory-2025-01-30.xml',
|
|
69
|
-
s3Key: 'exports/inventory-2025-01-30.xml'
|
|
70
|
-
});
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## API Reference
|
|
76
|
-
|
|
77
|
-
### Constructor
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
new JobTracker(
|
|
81
|
-
kv: KVAdapter,
|
|
82
|
-
logger: StructuredLogger,
|
|
83
|
-
ttl?: number
|
|
84
|
-
)
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
**Parameters:**
|
|
88
|
-
- `kv` - KV adapter (VersoriKVAdapter or custom implementation)
|
|
89
|
-
- `logger` - Structured logger
|
|
90
|
-
- `ttl` - Optional TTL in seconds (default: 604800 = 7 days)
|
|
91
|
-
|
|
92
|
-
**Example:**
|
|
93
|
-
```typescript
|
|
94
|
-
const tracker = new JobTracker(
|
|
95
|
-
kvAdapter,
|
|
96
|
-
logger,
|
|
97
|
-
86400 // 24 hours
|
|
98
|
-
);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
### createJob()
|
|
104
|
-
|
|
105
|
-
Create a new job with 'queued' status.
|
|
106
|
-
|
|
107
|
-
```typescript
|
|
108
|
-
await tracker.createJob(
|
|
109
|
-
jobId: string,
|
|
110
|
-
metadata: Partial<JobStatus>
|
|
111
|
-
): Promise<void>
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
**Parameters:**
|
|
115
|
-
- `jobId` - Unique job identifier (recommend timestamp-based: `scheduled_${Date.now()}`)
|
|
116
|
-
- `metadata` - Initial job metadata
|
|
117
|
-
- `triggeredBy` - 'schedule' | 'webhook' | 'manual'
|
|
118
|
-
- `stage` - Current processing stage (optional)
|
|
119
|
-
- `message` - Human-readable message (optional)
|
|
120
|
-
- `details` - Additional job-specific data (optional)
|
|
121
|
-
|
|
122
|
-
**Example:**
|
|
123
|
-
```typescript
|
|
124
|
-
await tracker.createJob('webhook_1706356800000', {
|
|
125
|
-
triggeredBy: 'webhook',
|
|
126
|
-
stage: 'validation',
|
|
127
|
-
message: 'Processing webhook payload',
|
|
128
|
-
details: {
|
|
129
|
-
webhookId: 'wh_123',
|
|
130
|
-
source: 'shopify'
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
### updateJob()
|
|
138
|
-
|
|
139
|
-
Update job status and metadata.
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
await tracker.updateJob(
|
|
143
|
-
jobId: string,
|
|
144
|
-
updates: Partial<JobStatus>
|
|
145
|
-
): Promise<void>
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**Parameters:**
|
|
149
|
-
- `jobId` - Job identifier
|
|
150
|
-
- `updates` - Fields to update
|
|
151
|
-
- `status` - 'queued' | 'processing' | 'completed' | 'failed'
|
|
152
|
-
- `stage` - Current processing stage
|
|
153
|
-
- `message` - Status message
|
|
154
|
-
- `details` - Additional metadata (merged with existing)
|
|
155
|
-
|
|
156
|
-
**Example:**
|
|
157
|
-
```typescript
|
|
158
|
-
// Update stage
|
|
159
|
-
await tracker.updateJob(jobId, {
|
|
160
|
-
stage: 'transformation',
|
|
161
|
-
message: 'Mapping 500 records'
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// Update status and stage
|
|
165
|
-
await tracker.updateJob(jobId, {
|
|
166
|
-
status: 'processing',
|
|
167
|
-
stage: 'ingestion',
|
|
168
|
-
message: 'Submitting batches to Fluent API',
|
|
169
|
-
details: {
|
|
170
|
-
batchCount: 5,
|
|
171
|
-
recordsPerBatch: 100
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
### markCompleted()
|
|
179
|
-
|
|
180
|
-
Mark job as successfully completed.
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
await tracker.markCompleted(
|
|
184
|
-
jobId: string,
|
|
185
|
-
finalDetails?: Record<string, any>
|
|
186
|
-
): Promise<void>
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
**Parameters:**
|
|
190
|
-
- `jobId` - Job identifier
|
|
191
|
-
- `finalDetails` - Optional final metadata
|
|
192
|
-
|
|
193
|
-
**Automatically sets:**
|
|
194
|
-
- `status` = 'completed'
|
|
195
|
-
- `completedAt` = current timestamp
|
|
196
|
-
|
|
197
|
-
**Example:**
|
|
198
|
-
```typescript
|
|
199
|
-
await tracker.markCompleted(jobId, {
|
|
200
|
-
recordCount: 1000,
|
|
201
|
-
successCount: 995,
|
|
202
|
-
failedCount: 5,
|
|
203
|
-
durationMs: 45000,
|
|
204
|
-
fileName: 'export.xml',
|
|
205
|
-
s3Key: 'exports/2025/01/30/export.xml'
|
|
206
|
-
});
|
|
207
|
-
```
|
|
208
|
-
|
|
209
|
-
---
|
|
210
|
-
|
|
211
|
-
### markFailed()
|
|
212
|
-
|
|
213
|
-
Mark job as failed with error details.
|
|
214
|
-
|
|
215
|
-
```typescript
|
|
216
|
-
await tracker.markFailed(
|
|
217
|
-
jobId: string,
|
|
218
|
-
error: Error | string
|
|
219
|
-
): Promise<void>
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
**Parameters:**
|
|
223
|
-
- `jobId` - Job identifier
|
|
224
|
-
- `error` - Error object or message
|
|
225
|
-
|
|
226
|
-
**Automatically sets:**
|
|
227
|
-
- `status` = 'failed'
|
|
228
|
-
- `stage` = 'error'
|
|
229
|
-
- `failedAt` = current timestamp
|
|
230
|
-
- `message` = `"Job failed: {error message}"`
|
|
231
|
-
- `error` = error message
|
|
232
|
-
- `errorStack` = stack trace (if Error object)
|
|
233
|
-
|
|
234
|
-
**Example:**
|
|
235
|
-
```typescript
|
|
236
|
-
try {
|
|
237
|
-
await processWorkflow();
|
|
238
|
-
} catch (error) {
|
|
239
|
-
await tracker.markFailed(jobId, error);
|
|
240
|
-
throw error;
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
---
|
|
245
|
-
|
|
246
|
-
### getJob()
|
|
247
|
-
|
|
248
|
-
Retrieve current job status.
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
const status = await tracker.getJob(
|
|
252
|
-
jobId: string
|
|
253
|
-
): Promise<JobStatus | undefined>
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
**Returns:**
|
|
257
|
-
- `JobStatus` object if job exists
|
|
258
|
-
- `undefined` if job not found
|
|
259
|
-
|
|
260
|
-
**Example:**
|
|
261
|
-
```typescript
|
|
262
|
-
const status = await tracker.getJob(jobId);
|
|
263
|
-
|
|
264
|
-
if (status) {
|
|
265
|
-
console.log(`Job ${jobId} status: ${status.status}`);
|
|
266
|
-
console.log(`Current stage: ${status.stage}`);
|
|
267
|
-
console.log(`Message: ${status.message}`);
|
|
268
|
-
|
|
269
|
-
if (status.status === 'failed') {
|
|
270
|
-
console.error('Error:', status.error);
|
|
271
|
-
}
|
|
272
|
-
} else {
|
|
273
|
-
console.log('Job not found or expired');
|
|
274
|
-
}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
## JobStatus Type
|
|
280
|
-
|
|
281
|
-
```typescript
|
|
282
|
-
interface JobStatus {
|
|
283
|
-
status: 'queued' | 'processing' | 'completed' | 'failed';
|
|
284
|
-
stage?: string;
|
|
285
|
-
message?: string;
|
|
286
|
-
createdAt?: string; // ISO 8601 timestamp
|
|
287
|
-
startedAt?: string; // Set when status becomes 'processing'
|
|
288
|
-
completedAt?: string; // Set by markCompleted()
|
|
289
|
-
failedAt?: string; // Set by markFailed()
|
|
290
|
-
triggeredBy: 'schedule' | 'webhook' | 'manual';
|
|
291
|
-
details?: Record<string, any>;
|
|
292
|
-
error?: string; // Error message if failed
|
|
293
|
-
errorStack?: string; // Stack trace if failed
|
|
294
|
-
}
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## Common Patterns
|
|
300
|
-
|
|
301
|
-
### Pattern 1: Scheduled Workflow
|
|
302
|
-
|
|
303
|
-
```typescript
|
|
304
|
-
export const dailySync = schedule('daily-sync', '0 0 * * *').then(
|
|
305
|
-
http('process', { connection: 'fluent' }, async ctx => {
|
|
306
|
-
const { log, openKv } = ctx;
|
|
307
|
-
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
308
|
-
const tracker = new JobTracker(kv, log);
|
|
309
|
-
|
|
310
|
-
const jobId = `daily_sync_${Date.now()}`;
|
|
311
|
-
|
|
312
|
-
try {
|
|
313
|
-
// Create job
|
|
314
|
-
await tracker.createJob(jobId, {
|
|
315
|
-
triggeredBy: 'schedule',
|
|
316
|
-
stage: 'initialization'
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// Extract
|
|
320
|
-
await tracker.updateJob(jobId, {
|
|
321
|
-
status: 'processing',
|
|
322
|
-
stage: 'extraction',
|
|
323
|
-
message: 'Extracting inventory data from Fluent'
|
|
324
|
-
});
|
|
325
|
-
const data = await extractInventory(client);
|
|
326
|
-
|
|
327
|
-
// Transform
|
|
328
|
-
await tracker.updateJob(jobId, {
|
|
329
|
-
stage: 'transformation',
|
|
330
|
-
message: `Transforming ${data.length} records`
|
|
331
|
-
});
|
|
332
|
-
const transformed = await transformData(data);
|
|
333
|
-
|
|
334
|
-
// Export
|
|
335
|
-
await tracker.updateJob(jobId, {
|
|
336
|
-
stage: 'export',
|
|
337
|
-
message: 'Uploading to SFTP'
|
|
338
|
-
});
|
|
339
|
-
await uploadToSftp(transformed);
|
|
340
|
-
|
|
341
|
-
// Complete
|
|
342
|
-
await tracker.markCompleted(jobId, {
|
|
343
|
-
recordCount: data.length,
|
|
344
|
-
fileName: 'export.xml'
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
} catch (error) {
|
|
348
|
-
await tracker.markFailed(jobId, error);
|
|
349
|
-
throw error;
|
|
350
|
-
}
|
|
351
|
-
})
|
|
352
|
-
);
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
---
|
|
356
|
-
|
|
357
|
-
### Pattern 2: Webhook Handler
|
|
358
|
-
|
|
359
|
-
```typescript
|
|
360
|
-
export const webhookHandler = webhook('inventory-update', {
|
|
361
|
-
response: {
|
|
362
|
-
mode: 'sync',
|
|
363
|
-
onSuccess: (ctx) => new Response(
|
|
364
|
-
JSON.stringify({ status: 'accepted', jobId: ctx.data.jobId }),
|
|
365
|
-
{ status: 202, headers: { 'Content-Type': 'application/json' } }
|
|
366
|
-
)
|
|
367
|
-
}
|
|
368
|
-
}, async ctx => {
|
|
369
|
-
const { log, openKv, request } = ctx;
|
|
370
|
-
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
371
|
-
const tracker = new JobTracker(kv, log);
|
|
372
|
-
|
|
373
|
-
const jobId = `webhook_${Date.now()}`;
|
|
374
|
-
|
|
375
|
-
try {
|
|
376
|
-
// Create job
|
|
377
|
-
await tracker.createJob(jobId, {
|
|
378
|
-
triggeredBy: 'webhook',
|
|
379
|
-
stage: 'validation',
|
|
380
|
-
message: 'Validating webhook payload'
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
// Validate
|
|
384
|
-
const payload = await request.json();
|
|
385
|
-
validatePayload(payload);
|
|
386
|
-
|
|
387
|
-
// Process
|
|
388
|
-
await tracker.updateJob(jobId, {
|
|
389
|
-
status: 'processing',
|
|
390
|
-
stage: 'ingestion',
|
|
391
|
-
message: `Ingesting ${payload.items.length} items`
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
await processInventory(payload);
|
|
395
|
-
|
|
396
|
-
// Complete
|
|
397
|
-
await tracker.markCompleted(jobId, {
|
|
398
|
-
itemCount: payload.items.length
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
return { jobId, status: 'completed' };
|
|
402
|
-
|
|
403
|
-
} catch (error) {
|
|
404
|
-
await tracker.markFailed(jobId, error);
|
|
405
|
-
throw error;
|
|
406
|
-
}
|
|
407
|
-
});
|
|
408
|
-
```
|
|
409
|
-
|
|
410
|
-
---
|
|
411
|
-
|
|
412
|
-
### Pattern 3: Job Retry Logic
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
async function processWithRetry(jobId: string, maxRetries = 3) {
|
|
416
|
-
const tracker = new JobTracker(kv, logger);
|
|
417
|
-
|
|
418
|
-
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
419
|
-
try {
|
|
420
|
-
await tracker.updateJob(jobId, {
|
|
421
|
-
status: 'processing',
|
|
422
|
-
message: `Attempt ${attempt}/${maxRetries}`
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
await processWorkflow();
|
|
426
|
-
|
|
427
|
-
await tracker.markCompleted(jobId, {
|
|
428
|
-
attempts: attempt
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
return; // Success
|
|
432
|
-
|
|
433
|
-
} catch (error) {
|
|
434
|
-
if (attempt === maxRetries) {
|
|
435
|
-
// Final attempt failed - update with details before marking failed
|
|
436
|
-
await tracker.updateJob(jobId, {
|
|
437
|
-
details: {
|
|
438
|
-
attempts: attempt,
|
|
439
|
-
maxRetries
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
await tracker.markFailed(jobId, error);
|
|
443
|
-
throw error;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
// Retry
|
|
447
|
-
await tracker.updateJob(jobId, {
|
|
448
|
-
message: `Attempt ${attempt} failed, retrying...`,
|
|
449
|
-
details: { lastError: error.message }
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
await sleep(1000 * attempt); // Exponential backoff
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
### Pattern 4: Dashboard Status Display
|
|
461
|
-
|
|
462
|
-
```typescript
|
|
463
|
-
// Get status for dashboard
|
|
464
|
-
const recentJobs = await Promise.all(
|
|
465
|
-
jobIds.map(id => tracker.getJob(id))
|
|
466
|
-
);
|
|
467
|
-
|
|
468
|
-
const summary = {
|
|
469
|
-
total: recentJobs.length,
|
|
470
|
-
completed: recentJobs.filter(j => j?.status === 'completed').length,
|
|
471
|
-
processing: recentJobs.filter(j => j?.status === 'processing').length,
|
|
472
|
-
failed: recentJobs.filter(j => j?.status === 'failed').length,
|
|
473
|
-
queued: recentJobs.filter(j => j?.status === 'queued').length
|
|
474
|
-
};
|
|
475
|
-
|
|
476
|
-
console.log('Job Summary:', summary);
|
|
477
|
-
|
|
478
|
-
// Show currently processing jobs
|
|
479
|
-
const activeJobs = recentJobs.filter(j => j?.status === 'processing');
|
|
480
|
-
activeJobs.forEach(job => {
|
|
481
|
-
console.log(`${job.stage}: ${job.message}`);
|
|
482
|
-
});
|
|
483
|
-
```
|
|
484
|
-
|
|
485
|
-
---
|
|
486
|
-
|
|
487
|
-
## TTL and Cleanup
|
|
488
|
-
|
|
489
|
-
Jobs are automatically cleaned up after TTL expires.
|
|
490
|
-
|
|
491
|
-
**Default TTL:** 7 days (604800 seconds)
|
|
492
|
-
|
|
493
|
-
**Custom TTL:**
|
|
494
|
-
```typescript
|
|
495
|
-
// 24 hours
|
|
496
|
-
const tracker = new JobTracker(kv, logger, 86400);
|
|
497
|
-
|
|
498
|
-
// 30 days
|
|
499
|
-
const tracker = new JobTracker(kv, logger, 2592000);
|
|
500
|
-
```
|
|
501
|
-
|
|
502
|
-
**Disable TTL:**
|
|
503
|
-
```typescript
|
|
504
|
-
const tracker = new JobTracker(kv, logger, 0);
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
---
|
|
508
|
-
|
|
509
|
-
## Error Handling
|
|
510
|
-
|
|
511
|
-
`JobTracker` is designed to never throw on KV errors. All operations log warnings but continue execution.
|
|
512
|
-
|
|
513
|
-
```typescript
|
|
514
|
-
// Safe - never throws
|
|
515
|
-
await tracker.createJob(jobId, metadata);
|
|
516
|
-
await tracker.updateJob(jobId, updates);
|
|
517
|
-
await tracker.markCompleted(jobId);
|
|
518
|
-
|
|
519
|
-
// Even if KV is unavailable, your workflow continues
|
|
520
|
-
```
|
|
521
|
-
|
|
522
|
-
**Logging:**
|
|
523
|
-
```typescript
|
|
524
|
-
// On KV error, tracker logs warning:
|
|
525
|
-
logger.warn('Failed to update job status', {
|
|
526
|
-
jobId,
|
|
527
|
-
error: error.message
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
// But doesn't throw - your workflow continues
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
---
|
|
534
|
-
|
|
535
|
-
### 1. Use Timestamp-Based Job IDs
|
|
536
|
-
|
|
537
|
-
```typescript
|
|
538
|
-
const jobId = `scheduled_${Date.now()}`;
|
|
539
|
-
const jobId = `inventory_sync_${Date.now()}`;
|
|
540
|
-
```
|
|
541
|
-
|
|
542
|
-
### 2. Update Stage Frequently
|
|
543
|
-
|
|
544
|
-
```typescript
|
|
545
|
-
await tracker.updateJob(jobId, { stage: 'extraction', message: 'Fetching data' });
|
|
546
|
-
await tracker.updateJob(jobId, { stage: 'transformation', message: 'Mapping 1000 records' });
|
|
547
|
-
await tracker.updateJob(jobId, { stage: 'validation', message: 'Validating entities' });
|
|
548
|
-
await tracker.updateJob(jobId, { stage: 'ingestion', message: 'Submitting batches' });
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
### 3. Include Useful Details
|
|
552
|
-
|
|
553
|
-
```typescript
|
|
554
|
-
await tracker.markCompleted(jobId, {
|
|
555
|
-
recordCount: 1000,
|
|
556
|
-
successCount: 995,
|
|
557
|
-
failedCount: 5,
|
|
558
|
-
durationMs: 45000,
|
|
559
|
-
s3Key: 'exports/file.xml',
|
|
560
|
-
batchCount: 10
|
|
561
|
-
});
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
### 4. Always Mark Failed Jobs
|
|
565
|
-
|
|
566
|
-
```typescript
|
|
567
|
-
try {
|
|
568
|
-
await processWorkflow();
|
|
569
|
-
await tracker.markCompleted(jobId);
|
|
570
|
-
} catch (error) {
|
|
571
|
-
await tracker.markFailed(jobId, error);
|
|
572
|
-
throw error;
|
|
573
|
-
}
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
---
|
|
577
|
-
|
|
578
|
-
## Troubleshooting
|
|
579
|
-
|
|
580
|
-
### Job Not Found
|
|
581
|
-
|
|
582
|
-
**Problem:** `getJob()` returns `undefined`
|
|
583
|
-
|
|
584
|
-
**Causes:**
|
|
585
|
-
1. Job expired (TTL reached)
|
|
586
|
-
2. Wrong jobId
|
|
587
|
-
3. KV store cleared
|
|
588
|
-
|
|
589
|
-
**Solution:**
|
|
590
|
-
```typescript
|
|
591
|
-
const status = await tracker.getJob(jobId);
|
|
592
|
-
if (!status) {
|
|
593
|
-
logger.warn('Job not found', { jobId });
|
|
594
|
-
// Handle missing job
|
|
595
|
-
}
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
### Jobs Stuck in 'processing'
|
|
599
|
-
|
|
600
|
-
**Problem:** Jobs never reach 'completed' or 'failed'
|
|
601
|
-
|
|
602
|
-
**Cause:** Missing `markCompleted()` or `markFailed()` calls
|
|
603
|
-
|
|
604
|
-
**Solution:**
|
|
605
|
-
```typescript
|
|
606
|
-
// Always wrap in try/catch
|
|
607
|
-
try {
|
|
608
|
-
await processWorkflow();
|
|
609
|
-
await tracker.markCompleted(jobId); // ✅
|
|
610
|
-
} catch (error) {
|
|
611
|
-
await tracker.markFailed(jobId, error); // ✅
|
|
612
|
-
throw error;
|
|
613
|
-
}
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
---
|
|
617
|
-
|
|
618
|
-
## See Also
|
|
619
|
-
|
|
620
|
-
- [PartialBatchRecovery](./advanced-services-partial-batch-recovery.md) - Recover from partial failures
|
|
621
|
-
- [State Management](../ingestion/modules/02-core-guides-ingestion-07-state-management.md) - File tracking
|
|
622
|
-
- [Monitoring](./advanced-services-quick-reference.md) - Processing metrics (see JobTracker section)
|
|
623
|
-
- [Advanced Services Overview](./advanced-services-readme.md) - All advanced services
|
|
624
|
-
|
|
625
|
-
---
|
|
626
|
-
|
|
627
|
-
[← Back to Advanced Services](./advanced-services-readme.md) | [Next: PartialBatchRecovery →](./advanced-services-partial-batch-recovery.md)
|
|
1
|
+
# JobTracker
|
|
2
|
+
|
|
3
|
+
**Level:** Advanced
|
|
4
|
+
**Category:** Production Services
|
|
5
|
+
**Purpose:** Track job lifecycle and status across workflows
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
`JobTracker` provides standardized job status tracking for Fluent Commerce integrations. It manages job lifecycle from creation through completion or failure, with automatic timestamp tracking and TTL support for cleanup.
|
|
10
|
+
|
|
11
|
+
## Use Cases
|
|
12
|
+
|
|
13
|
+
- ✅ Monitor scheduled workflow progress
|
|
14
|
+
- ✅ Track webhook-triggered operations
|
|
15
|
+
- ✅ Implement job retry logic
|
|
16
|
+
- ✅ Display job status in dashboards
|
|
17
|
+
- ✅ Debug failed jobs in production
|
|
18
|
+
- ✅ Track processing stages (extraction → transformation → ingestion)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { JobTracker, VersoriKVAdapter } from '@fluentcommerce/fc-connect-sdk';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Basic Usage
|
|
31
|
+
|
|
32
|
+
### Create and Track a Job
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { JobTracker, VersoriKVAdapter } from '@fluentcommerce/fc-connect-sdk';
|
|
36
|
+
|
|
37
|
+
// Initialize tracker
|
|
38
|
+
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
39
|
+
const tracker = new JobTracker(kv, logger);
|
|
40
|
+
|
|
41
|
+
// Create job
|
|
42
|
+
const jobId = `scheduled_${Date.now()}`;
|
|
43
|
+
await tracker.createJob(jobId, {
|
|
44
|
+
triggeredBy: 'schedule',
|
|
45
|
+
stage: 'initialization',
|
|
46
|
+
details: {
|
|
47
|
+
catalogueRef: 'DEFAULT:1',
|
|
48
|
+
workflow: 'inventory-sync'
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Update as processing
|
|
53
|
+
await tracker.updateJob(jobId, {
|
|
54
|
+
status: 'processing',
|
|
55
|
+
stage: 'extraction',
|
|
56
|
+
message: 'Extracting inventory positions'
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Update stage
|
|
60
|
+
await tracker.updateJob(jobId, {
|
|
61
|
+
stage: 'transformation',
|
|
62
|
+
message: 'Transforming 1000 records'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Mark complete
|
|
66
|
+
await tracker.markCompleted(jobId, {
|
|
67
|
+
recordCount: 1000,
|
|
68
|
+
fileName: 'inventory-2025-01-30.xml',
|
|
69
|
+
s3Key: 'exports/inventory-2025-01-30.xml'
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## API Reference
|
|
76
|
+
|
|
77
|
+
### Constructor
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
new JobTracker(
|
|
81
|
+
kv: KVAdapter,
|
|
82
|
+
logger: StructuredLogger,
|
|
83
|
+
ttl?: number
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Parameters:**
|
|
88
|
+
- `kv` - KV adapter (VersoriKVAdapter or custom implementation)
|
|
89
|
+
- `logger` - Structured logger
|
|
90
|
+
- `ttl` - Optional TTL in seconds (default: 604800 = 7 days)
|
|
91
|
+
|
|
92
|
+
**Example:**
|
|
93
|
+
```typescript
|
|
94
|
+
const tracker = new JobTracker(
|
|
95
|
+
kvAdapter,
|
|
96
|
+
logger,
|
|
97
|
+
86400 // 24 hours
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### createJob()
|
|
104
|
+
|
|
105
|
+
Create a new job with 'queued' status.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
await tracker.createJob(
|
|
109
|
+
jobId: string,
|
|
110
|
+
metadata: Partial<JobStatus>
|
|
111
|
+
): Promise<void>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Parameters:**
|
|
115
|
+
- `jobId` - Unique job identifier (recommend timestamp-based: `scheduled_${Date.now()}`)
|
|
116
|
+
- `metadata` - Initial job metadata
|
|
117
|
+
- `triggeredBy` - 'schedule' | 'webhook' | 'manual'
|
|
118
|
+
- `stage` - Current processing stage (optional)
|
|
119
|
+
- `message` - Human-readable message (optional)
|
|
120
|
+
- `details` - Additional job-specific data (optional)
|
|
121
|
+
|
|
122
|
+
**Example:**
|
|
123
|
+
```typescript
|
|
124
|
+
await tracker.createJob('webhook_1706356800000', {
|
|
125
|
+
triggeredBy: 'webhook',
|
|
126
|
+
stage: 'validation',
|
|
127
|
+
message: 'Processing webhook payload',
|
|
128
|
+
details: {
|
|
129
|
+
webhookId: 'wh_123',
|
|
130
|
+
source: 'shopify'
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### updateJob()
|
|
138
|
+
|
|
139
|
+
Update job status and metadata.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
await tracker.updateJob(
|
|
143
|
+
jobId: string,
|
|
144
|
+
updates: Partial<JobStatus>
|
|
145
|
+
): Promise<void>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
- `jobId` - Job identifier
|
|
150
|
+
- `updates` - Fields to update
|
|
151
|
+
- `status` - 'queued' | 'processing' | 'completed' | 'failed'
|
|
152
|
+
- `stage` - Current processing stage
|
|
153
|
+
- `message` - Status message
|
|
154
|
+
- `details` - Additional metadata (merged with existing)
|
|
155
|
+
|
|
156
|
+
**Example:**
|
|
157
|
+
```typescript
|
|
158
|
+
// Update stage
|
|
159
|
+
await tracker.updateJob(jobId, {
|
|
160
|
+
stage: 'transformation',
|
|
161
|
+
message: 'Mapping 500 records'
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Update status and stage
|
|
165
|
+
await tracker.updateJob(jobId, {
|
|
166
|
+
status: 'processing',
|
|
167
|
+
stage: 'ingestion',
|
|
168
|
+
message: 'Submitting batches to Fluent API',
|
|
169
|
+
details: {
|
|
170
|
+
batchCount: 5,
|
|
171
|
+
recordsPerBatch: 100
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### markCompleted()
|
|
179
|
+
|
|
180
|
+
Mark job as successfully completed.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
await tracker.markCompleted(
|
|
184
|
+
jobId: string,
|
|
185
|
+
finalDetails?: Record<string, any>
|
|
186
|
+
): Promise<void>
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Parameters:**
|
|
190
|
+
- `jobId` - Job identifier
|
|
191
|
+
- `finalDetails` - Optional final metadata
|
|
192
|
+
|
|
193
|
+
**Automatically sets:**
|
|
194
|
+
- `status` = 'completed'
|
|
195
|
+
- `completedAt` = current timestamp
|
|
196
|
+
|
|
197
|
+
**Example:**
|
|
198
|
+
```typescript
|
|
199
|
+
await tracker.markCompleted(jobId, {
|
|
200
|
+
recordCount: 1000,
|
|
201
|
+
successCount: 995,
|
|
202
|
+
failedCount: 5,
|
|
203
|
+
durationMs: 45000,
|
|
204
|
+
fileName: 'export.xml',
|
|
205
|
+
s3Key: 'exports/2025/01/30/export.xml'
|
|
206
|
+
});
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### markFailed()
|
|
212
|
+
|
|
213
|
+
Mark job as failed with error details.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
await tracker.markFailed(
|
|
217
|
+
jobId: string,
|
|
218
|
+
error: Error | string
|
|
219
|
+
): Promise<void>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Parameters:**
|
|
223
|
+
- `jobId` - Job identifier
|
|
224
|
+
- `error` - Error object or message
|
|
225
|
+
|
|
226
|
+
**Automatically sets:**
|
|
227
|
+
- `status` = 'failed'
|
|
228
|
+
- `stage` = 'error'
|
|
229
|
+
- `failedAt` = current timestamp
|
|
230
|
+
- `message` = `"Job failed: {error message}"`
|
|
231
|
+
- `error` = error message
|
|
232
|
+
- `errorStack` = stack trace (if Error object)
|
|
233
|
+
|
|
234
|
+
**Example:**
|
|
235
|
+
```typescript
|
|
236
|
+
try {
|
|
237
|
+
await processWorkflow();
|
|
238
|
+
} catch (error) {
|
|
239
|
+
await tracker.markFailed(jobId, error);
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
### getJob()
|
|
247
|
+
|
|
248
|
+
Retrieve current job status.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
const status = await tracker.getJob(
|
|
252
|
+
jobId: string
|
|
253
|
+
): Promise<JobStatus | undefined>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Returns:**
|
|
257
|
+
- `JobStatus` object if job exists
|
|
258
|
+
- `undefined` if job not found
|
|
259
|
+
|
|
260
|
+
**Example:**
|
|
261
|
+
```typescript
|
|
262
|
+
const status = await tracker.getJob(jobId);
|
|
263
|
+
|
|
264
|
+
if (status) {
|
|
265
|
+
console.log(`Job ${jobId} status: ${status.status}`);
|
|
266
|
+
console.log(`Current stage: ${status.stage}`);
|
|
267
|
+
console.log(`Message: ${status.message}`);
|
|
268
|
+
|
|
269
|
+
if (status.status === 'failed') {
|
|
270
|
+
console.error('Error:', status.error);
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
console.log('Job not found or expired');
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## JobStatus Type
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
interface JobStatus {
|
|
283
|
+
status: 'queued' | 'processing' | 'completed' | 'failed';
|
|
284
|
+
stage?: string;
|
|
285
|
+
message?: string;
|
|
286
|
+
createdAt?: string; // ISO 8601 timestamp
|
|
287
|
+
startedAt?: string; // Set when status becomes 'processing'
|
|
288
|
+
completedAt?: string; // Set by markCompleted()
|
|
289
|
+
failedAt?: string; // Set by markFailed()
|
|
290
|
+
triggeredBy: 'schedule' | 'webhook' | 'manual';
|
|
291
|
+
details?: Record<string, any>;
|
|
292
|
+
error?: string; // Error message if failed
|
|
293
|
+
errorStack?: string; // Stack trace if failed
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Common Patterns
|
|
300
|
+
|
|
301
|
+
### Pattern 1: Scheduled Workflow
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
export const dailySync = schedule('daily-sync', '0 0 * * *').then(
|
|
305
|
+
http('process', { connection: 'fluent' }, async ctx => {
|
|
306
|
+
const { log, openKv } = ctx;
|
|
307
|
+
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
308
|
+
const tracker = new JobTracker(kv, log);
|
|
309
|
+
|
|
310
|
+
const jobId = `daily_sync_${Date.now()}`;
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
// Create job
|
|
314
|
+
await tracker.createJob(jobId, {
|
|
315
|
+
triggeredBy: 'schedule',
|
|
316
|
+
stage: 'initialization'
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Extract
|
|
320
|
+
await tracker.updateJob(jobId, {
|
|
321
|
+
status: 'processing',
|
|
322
|
+
stage: 'extraction',
|
|
323
|
+
message: 'Extracting inventory data from Fluent'
|
|
324
|
+
});
|
|
325
|
+
const data = await extractInventory(client);
|
|
326
|
+
|
|
327
|
+
// Transform
|
|
328
|
+
await tracker.updateJob(jobId, {
|
|
329
|
+
stage: 'transformation',
|
|
330
|
+
message: `Transforming ${data.length} records`
|
|
331
|
+
});
|
|
332
|
+
const transformed = await transformData(data);
|
|
333
|
+
|
|
334
|
+
// Export
|
|
335
|
+
await tracker.updateJob(jobId, {
|
|
336
|
+
stage: 'export',
|
|
337
|
+
message: 'Uploading to SFTP'
|
|
338
|
+
});
|
|
339
|
+
await uploadToSftp(transformed);
|
|
340
|
+
|
|
341
|
+
// Complete
|
|
342
|
+
await tracker.markCompleted(jobId, {
|
|
343
|
+
recordCount: data.length,
|
|
344
|
+
fileName: 'export.xml'
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
} catch (error) {
|
|
348
|
+
await tracker.markFailed(jobId, error);
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
351
|
+
})
|
|
352
|
+
);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### Pattern 2: Webhook Handler
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
export const webhookHandler = webhook('inventory-update', {
|
|
361
|
+
response: {
|
|
362
|
+
mode: 'sync',
|
|
363
|
+
onSuccess: (ctx) => new Response(
|
|
364
|
+
JSON.stringify({ status: 'accepted', jobId: ctx.data.jobId }),
|
|
365
|
+
{ status: 202, headers: { 'Content-Type': 'application/json' } }
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
}, async ctx => {
|
|
369
|
+
const { log, openKv, request } = ctx;
|
|
370
|
+
const kv = new VersoriKVAdapter(openKv(':project:'));
|
|
371
|
+
const tracker = new JobTracker(kv, log);
|
|
372
|
+
|
|
373
|
+
const jobId = `webhook_${Date.now()}`;
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
// Create job
|
|
377
|
+
await tracker.createJob(jobId, {
|
|
378
|
+
triggeredBy: 'webhook',
|
|
379
|
+
stage: 'validation',
|
|
380
|
+
message: 'Validating webhook payload'
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// Validate
|
|
384
|
+
const payload = await request.json();
|
|
385
|
+
validatePayload(payload);
|
|
386
|
+
|
|
387
|
+
// Process
|
|
388
|
+
await tracker.updateJob(jobId, {
|
|
389
|
+
status: 'processing',
|
|
390
|
+
stage: 'ingestion',
|
|
391
|
+
message: `Ingesting ${payload.items.length} items`
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
await processInventory(payload);
|
|
395
|
+
|
|
396
|
+
// Complete
|
|
397
|
+
await tracker.markCompleted(jobId, {
|
|
398
|
+
itemCount: payload.items.length
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
return { jobId, status: 'completed' };
|
|
402
|
+
|
|
403
|
+
} catch (error) {
|
|
404
|
+
await tracker.markFailed(jobId, error);
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### Pattern 3: Job Retry Logic
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
async function processWithRetry(jobId: string, maxRetries = 3) {
|
|
416
|
+
const tracker = new JobTracker(kv, logger);
|
|
417
|
+
|
|
418
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
419
|
+
try {
|
|
420
|
+
await tracker.updateJob(jobId, {
|
|
421
|
+
status: 'processing',
|
|
422
|
+
message: `Attempt ${attempt}/${maxRetries}`
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
await processWorkflow();
|
|
426
|
+
|
|
427
|
+
await tracker.markCompleted(jobId, {
|
|
428
|
+
attempts: attempt
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
return; // Success
|
|
432
|
+
|
|
433
|
+
} catch (error) {
|
|
434
|
+
if (attempt === maxRetries) {
|
|
435
|
+
// Final attempt failed - update with details before marking failed
|
|
436
|
+
await tracker.updateJob(jobId, {
|
|
437
|
+
details: {
|
|
438
|
+
attempts: attempt,
|
|
439
|
+
maxRetries
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
await tracker.markFailed(jobId, error);
|
|
443
|
+
throw error;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Retry
|
|
447
|
+
await tracker.updateJob(jobId, {
|
|
448
|
+
message: `Attempt ${attempt} failed, retrying...`,
|
|
449
|
+
details: { lastError: error.message }
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
await sleep(1000 * attempt); // Exponential backoff
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
### Pattern 4: Dashboard Status Display
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
// Get status for dashboard
|
|
464
|
+
const recentJobs = await Promise.all(
|
|
465
|
+
jobIds.map(id => tracker.getJob(id))
|
|
466
|
+
);
|
|
467
|
+
|
|
468
|
+
const summary = {
|
|
469
|
+
total: recentJobs.length,
|
|
470
|
+
completed: recentJobs.filter(j => j?.status === 'completed').length,
|
|
471
|
+
processing: recentJobs.filter(j => j?.status === 'processing').length,
|
|
472
|
+
failed: recentJobs.filter(j => j?.status === 'failed').length,
|
|
473
|
+
queued: recentJobs.filter(j => j?.status === 'queued').length
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
console.log('Job Summary:', summary);
|
|
477
|
+
|
|
478
|
+
// Show currently processing jobs
|
|
479
|
+
const activeJobs = recentJobs.filter(j => j?.status === 'processing');
|
|
480
|
+
activeJobs.forEach(job => {
|
|
481
|
+
console.log(`${job.stage}: ${job.message}`);
|
|
482
|
+
});
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
---
|
|
486
|
+
|
|
487
|
+
## TTL and Cleanup
|
|
488
|
+
|
|
489
|
+
Jobs are automatically cleaned up after TTL expires.
|
|
490
|
+
|
|
491
|
+
**Default TTL:** 7 days (604800 seconds)
|
|
492
|
+
|
|
493
|
+
**Custom TTL:**
|
|
494
|
+
```typescript
|
|
495
|
+
// 24 hours
|
|
496
|
+
const tracker = new JobTracker(kv, logger, 86400);
|
|
497
|
+
|
|
498
|
+
// 30 days
|
|
499
|
+
const tracker = new JobTracker(kv, logger, 2592000);
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
**Disable TTL:**
|
|
503
|
+
```typescript
|
|
504
|
+
const tracker = new JobTracker(kv, logger, 0);
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## Error Handling
|
|
510
|
+
|
|
511
|
+
`JobTracker` is designed to never throw on KV errors. All operations log warnings but continue execution.
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
// Safe - never throws
|
|
515
|
+
await tracker.createJob(jobId, metadata);
|
|
516
|
+
await tracker.updateJob(jobId, updates);
|
|
517
|
+
await tracker.markCompleted(jobId);
|
|
518
|
+
|
|
519
|
+
// Even if KV is unavailable, your workflow continues
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
**Logging:**
|
|
523
|
+
```typescript
|
|
524
|
+
// On KV error, tracker logs warning:
|
|
525
|
+
logger.warn('Failed to update job status', {
|
|
526
|
+
jobId,
|
|
527
|
+
error: error.message
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
// But doesn't throw - your workflow continues
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
### 1. Use Timestamp-Based Job IDs
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
const jobId = `scheduled_${Date.now()}`;
|
|
539
|
+
const jobId = `inventory_sync_${Date.now()}`;
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
### 2. Update Stage Frequently
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
await tracker.updateJob(jobId, { stage: 'extraction', message: 'Fetching data' });
|
|
546
|
+
await tracker.updateJob(jobId, { stage: 'transformation', message: 'Mapping 1000 records' });
|
|
547
|
+
await tracker.updateJob(jobId, { stage: 'validation', message: 'Validating entities' });
|
|
548
|
+
await tracker.updateJob(jobId, { stage: 'ingestion', message: 'Submitting batches' });
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 3. Include Useful Details
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
await tracker.markCompleted(jobId, {
|
|
555
|
+
recordCount: 1000,
|
|
556
|
+
successCount: 995,
|
|
557
|
+
failedCount: 5,
|
|
558
|
+
durationMs: 45000,
|
|
559
|
+
s3Key: 'exports/file.xml',
|
|
560
|
+
batchCount: 10
|
|
561
|
+
});
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### 4. Always Mark Failed Jobs
|
|
565
|
+
|
|
566
|
+
```typescript
|
|
567
|
+
try {
|
|
568
|
+
await processWorkflow();
|
|
569
|
+
await tracker.markCompleted(jobId);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
await tracker.markFailed(jobId, error);
|
|
572
|
+
throw error;
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
---
|
|
577
|
+
|
|
578
|
+
## Troubleshooting
|
|
579
|
+
|
|
580
|
+
### Job Not Found
|
|
581
|
+
|
|
582
|
+
**Problem:** `getJob()` returns `undefined`
|
|
583
|
+
|
|
584
|
+
**Causes:**
|
|
585
|
+
1. Job expired (TTL reached)
|
|
586
|
+
2. Wrong jobId
|
|
587
|
+
3. KV store cleared
|
|
588
|
+
|
|
589
|
+
**Solution:**
|
|
590
|
+
```typescript
|
|
591
|
+
const status = await tracker.getJob(jobId);
|
|
592
|
+
if (!status) {
|
|
593
|
+
logger.warn('Job not found', { jobId });
|
|
594
|
+
// Handle missing job
|
|
595
|
+
}
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
### Jobs Stuck in 'processing'
|
|
599
|
+
|
|
600
|
+
**Problem:** Jobs never reach 'completed' or 'failed'
|
|
601
|
+
|
|
602
|
+
**Cause:** Missing `markCompleted()` or `markFailed()` calls
|
|
603
|
+
|
|
604
|
+
**Solution:**
|
|
605
|
+
```typescript
|
|
606
|
+
// Always wrap in try/catch
|
|
607
|
+
try {
|
|
608
|
+
await processWorkflow();
|
|
609
|
+
await tracker.markCompleted(jobId); // ✅
|
|
610
|
+
} catch (error) {
|
|
611
|
+
await tracker.markFailed(jobId, error); // ✅
|
|
612
|
+
throw error;
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## See Also
|
|
619
|
+
|
|
620
|
+
- [PartialBatchRecovery](./advanced-services-partial-batch-recovery.md) - Recover from partial failures
|
|
621
|
+
- [State Management](../ingestion/modules/02-core-guides-ingestion-07-state-management.md) - File tracking
|
|
622
|
+
- [Monitoring](./advanced-services-quick-reference.md) - Processing metrics (see JobTracker section)
|
|
623
|
+
- [Advanced Services Overview](./advanced-services-readme.md) - All advanced services
|
|
624
|
+
|
|
625
|
+
---
|
|
626
|
+
|
|
627
|
+
[← Back to Advanced Services](./advanced-services-readme.md) | [Next: PartialBatchRecovery →](./advanced-services-partial-batch-recovery.md)
|