From b371965d251fe00a721d11765f6bd1e54a77cb9c Mon Sep 17 00:00:00 2001 From: Lam Tran Date: Mon, 16 Oct 2017 11:25:53 +0200 Subject: [PATCH] feat(stock-import): add repeater on 409 errors (#67) fixes #66 --- src/coffee/stockimport.coffee | 30 ++++++++++++++++++++++++------ src/spec/stockimport.spec.coffee | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/coffee/stockimport.coffee b/src/coffee/stockimport.coffee index d265eb11..fb8019cd 100644 --- a/src/coffee/stockimport.coffee +++ b/src/coffee/stockimport.coffee @@ -12,12 +12,13 @@ xmlHelpers = require './xmlhelpers' class StockImport constructor: (@logger, options = {}) -> - options = _.defaults options, {user_agent: 'sphere-stock-import'} + options = _.defaults options, {user_agent: 'sphere-stock-import', max409Retries: 10} @sync = new InventorySync @client = new SphereClient options @csvHeaders = options.csvHeaders @csvDelimiter = options.csvDelimiter @customFieldMappings = new CustomFieldMappings() + @max409Retries = options.max409Retries @_resetSummary() _resetSummary: -> @@ -349,15 +350,32 @@ class StockImport posts = _.map inventoryEntries, (entry) => existingEntry = @_match(entry, existingEntries) if existingEntry? - synced = @sync.buildActions(entry, existingEntry) - if synced.shouldUpdate() - @client.inventoryEntries.byId(synced.getUpdateId()).update(synced.getUpdatePayload()) - else - Promise.resolve statusCode: 304 + @_updateInventory(entry, existingEntry) else @client.inventoryEntries.create(entry) debug 'About to send %s requests', _.size(posts) Promise.all(posts) + _updateInventory: (entry, existingEntry, tryCount = 1) => + synced = @sync.buildActions(entry, existingEntry) + if synced.shouldUpdate() + @client.inventoryEntries.byId(synced.getUpdateId()).update(synced.getUpdatePayload()) + .catch (err) => + if (err.statusCode == 409) + debug "Got 409 error for entry #{JSON.stringify(entry)}, repeat the request " + + "for #{tryCount} times." + if (tryCount <= @max409Retries) + @client.inventoryEntries + .byId(synced.getUpdateId()) + .fetch() + .then (result) => + @_updateInventory(entry, result.body, tryCount + 1) + else + Promise.reject new Error("Retry limit #{max409Retries} reached for stock #{JSON.stringify(entry)}") + else + Promise.reject err + else + Promise.resolve statusCode: 304 + module.exports = StockImport diff --git a/src/spec/stockimport.spec.coffee b/src/spec/stockimport.spec.coffee index 1fc3ba36..ab1117bf 100644 --- a/src/spec/stockimport.spec.coffee +++ b/src/spec/stockimport.spec.coffee @@ -533,6 +533,28 @@ describe 'StockImport', -> done() .catch (err) -> done(err) + it 'should repeat on 409 error', (done) -> + methodCalledCounter = 0 + inventoryEntries = [ + {sku: 'foo', quantityOnStock: 2}, + {sku: 'foo', quantityOnStock: 3, supplyChannel: {typeId: 'channel', id: '111'}} + ] + existingEntries = [{id: '123', version: 1, sku: 'foo', quantityOnStock: 1}] + + spyOn(@import.client.inventoryEntries, 'update').andCallFake () -> + methodCalledCounter++ + return Promise.reject({ statusCode: 409 }) + + spyOn(@import.client.inventoryEntries, 'fetch').andCallFake -> + new Promise (resolve, reject) -> resolve({body: existingEntries[0]}) + + @import._createOrUpdate inventoryEntries, existingEntries + .then => + done('Test should fail') + .catch () -> + expect(methodCalledCounter).toEqual(11) + done() + describe '::_match', ->