@rabbitio/ui-kit 1.0.0-beta.37 → 1.0.0-beta.39

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/dist/index.cjs CHANGED
@@ -1,12 +1,15 @@
1
1
  var React = require('react');
2
2
  var bignumber_js = require('bignumber.js');
3
3
  var axios = require('axios');
4
+ var uuid = require('uuid');
5
+ var Hashes = require('jshashes');
4
6
  var EventBusInstance = require('eventbusjs');
5
7
 
6
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
7
9
 
8
10
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
9
11
  var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
12
+ var Hashes__default = /*#__PURE__*/_interopDefaultLegacy(Hashes);
10
13
  var EventBusInstance__default = /*#__PURE__*/_interopDefaultLegacy(EventBusInstance);
11
14
 
12
15
  function createCommonjsModule(fn) {
@@ -1627,7 +1630,7 @@ var Logger = /*#__PURE__*/function () {
1627
1630
  return Logger;
1628
1631
  }();
1629
1632
 
1630
- function _catch$4(body, recover) {
1633
+ function _catch$8(body, recover) {
1631
1634
  try {
1632
1635
  var result = body();
1633
1636
  } catch (e) {
@@ -1643,7 +1646,7 @@ function useCallHandlingErrors() {
1643
1646
  setState = _useState[1];
1644
1647
  return React.useCallback(function (functionToBeCalled, event) {
1645
1648
  try {
1646
- var _temp = _catch$4(function () {
1649
+ var _temp = _catch$8(function () {
1647
1650
  return Promise.resolve(functionToBeCalled(event)).then(function () {});
1648
1651
  }, function (error) {
1649
1652
  Logger.logError(error, (functionToBeCalled == null ? void 0 : functionToBeCalled.name) || "errorBoundaryTrigger", "Caught by ErrorBoundary");
@@ -1681,6 +1684,96 @@ function useReferredState(initialValue) {
1681
1684
  return [reference, setReferredState];
1682
1685
  }
1683
1686
 
1687
+ var handleClickOutside = function handleClickOutside(exceptionsRefs, callback) {
1688
+ function handleClick(event) {
1689
+ var isExceptionClicked = exceptionsRefs.find(function (ref) {
1690
+ return (ref == null ? void 0 : ref.current) && ref.current.contains(event.target);
1691
+ });
1692
+ if (!isExceptionClicked) {
1693
+ callback();
1694
+ }
1695
+ }
1696
+ document.addEventListener("click", handleClick);
1697
+ return function () {
1698
+ return document.removeEventListener("click", handleClick);
1699
+ };
1700
+ };
1701
+
1702
+ var PARAMETER_VALUES_SEPARATOR = "|*|"; // Sting that with high probability will not be in the user's data
1703
+
1704
+ /**
1705
+ * Adds specified parameter with values to the URL query string
1706
+ *
1707
+ * @param parameterName - String - name of the parameter
1708
+ * @param values - Array of String values
1709
+ * @param updateURLCallback - callback that will be called with the updated query string. Can be used to save it to URL
1710
+ */
1711
+ function saveQueryParameterAndValues(parameterName, values, updateURLCallback) {
1712
+ if (updateURLCallback === void 0) {
1713
+ updateURLCallback = function updateURLCallback(newQueryString) {};
1714
+ }
1715
+ var parametersAndValues = parseSearchString();
1716
+ parametersAndValues = parametersAndValues.filter(function (parameterAndValues) {
1717
+ return parameterAndValues[0] !== parameterName;
1718
+ });
1719
+ var parameterValuesForURL = encodeURIComponent(values.join(PARAMETER_VALUES_SEPARATOR));
1720
+ parametersAndValues.push([parameterName, parameterValuesForURL]);
1721
+ var newQueryString = "?" + parametersAndValues.map(function (parameterAndValues) {
1722
+ return parameterAndValues.join("=");
1723
+ }).join("&");
1724
+ updateURLCallback(newQueryString);
1725
+ return newQueryString;
1726
+ }
1727
+
1728
+ /**
1729
+ * Removes specified parameter with values from the URL query string
1730
+ *
1731
+ * @param parameterName - String - name of the parameter
1732
+ * @param updateURLCallback - callback that will be called with the updated query string. Can be used to save it to URL
1733
+ */
1734
+ // TODO: [tests, moderate] units required the same as or other functions in this module
1735
+ function removeQueryParameterAndValues(parameterName, updateURLCallback) {
1736
+ if (updateURLCallback === void 0) {
1737
+ updateURLCallback = function updateURLCallback(newQueryString) {};
1738
+ }
1739
+ var parametersAndValues = parseSearchString();
1740
+ parametersAndValues = parametersAndValues.filter(function (parameterAndValues) {
1741
+ return parameterAndValues[0] !== parameterName;
1742
+ });
1743
+ var newQueryString = "?" + parametersAndValues.map(function (parameterAndValues) {
1744
+ return parameterAndValues.join("=");
1745
+ }).join("&");
1746
+ updateURLCallback(newQueryString);
1747
+ return newQueryString;
1748
+ }
1749
+
1750
+ /**
1751
+ * Retrieves parameter values from the URL query string.
1752
+ *
1753
+ * If there are several parameters with the same name in the URL then all their values are returned
1754
+ *
1755
+ * @param name {string} - parameter name
1756
+ * @return {string[]} [] - if the parameter is not present in URL. [""] - if parameter present but has empty value
1757
+ */
1758
+ function getQueryParameterValues(name) {
1759
+ return parseSearchString().filter(function (parameterAndValue) {
1760
+ return parameterAndValue[0] === name;
1761
+ }).reduce(function (allValues, parameterAndValue) {
1762
+ var values = decodeURIComponent(parameterAndValue[1] || "").split(PARAMETER_VALUES_SEPARATOR);
1763
+ return [].concat(allValues, values);
1764
+ }, []);
1765
+ }
1766
+ function parseSearchString() {
1767
+ var _window$location$sear;
1768
+ var trimmed = (((_window$location$sear = window.location.search) == null ? void 0 : _window$location$sear.slice(1)) || "").trim();
1769
+ return trimmed && trimmed.split("&").map(function (parameterAndValue) {
1770
+ return parameterAndValue.split("=");
1771
+ }) || [];
1772
+ }
1773
+ function getQueryParameterSingleValue(name) {
1774
+ return (getQueryParameterValues(name) || [])[0];
1775
+ }
1776
+
1684
1777
  /**
1685
1778
  * This function improves the passed error object (its message) by adding the passed function name
1686
1779
  * and additional message to it.
@@ -1709,6 +1802,17 @@ function improvedErrorMessage(e, settingFunction, additionalMessage) {
1709
1802
  additionalMessage && (message += additionalMessage + " ");
1710
1803
  return message;
1711
1804
  }
1805
+ function logErrorOrOutputToConsole(e) {
1806
+ try {
1807
+ // TODO: [dev] remove this after few weeks of testing output in real life
1808
+ // eslint-disable-next-line no-console
1809
+ console.log("BEFORE SAFE", e);
1810
+ Logger.log("logErrorOrOutputToConsole", safeStringify(e));
1811
+ } catch (e) {
1812
+ // eslint-disable-next-line no-console
1813
+ console.log("logErrorOrOutputToConsole", e);
1814
+ }
1815
+ }
1712
1816
 
1713
1817
  var FiatCurrenciesService = /*#__PURE__*/function () {
1714
1818
  function FiatCurrenciesService() {}
@@ -2580,7 +2684,109 @@ var Cache = /*#__PURE__*/function () {
2580
2684
  return Cache;
2581
2685
  }();
2582
2686
 
2583
- function _catch$3(body, recover) {
2687
+ function _catch$7(body, recover) {
2688
+ try {
2689
+ var result = body();
2690
+ } catch (e) {
2691
+ return recover(e);
2692
+ }
2693
+ if (result && result.then) {
2694
+ return result.then(void 0, recover);
2695
+ }
2696
+ return result;
2697
+ }
2698
+ function postponeExecution(execution, timeoutMS) {
2699
+ if (timeoutMS === void 0) {
2700
+ timeoutMS = 1000;
2701
+ }
2702
+ return new Promise(function (resolve, reject) {
2703
+ setTimeout(function () {
2704
+ try {
2705
+ var _temp = _catch$7(function () {
2706
+ return Promise.resolve(execution()).then(function (_execution) {
2707
+ resolve(_execution);
2708
+ });
2709
+ }, function (e) {
2710
+ reject(e);
2711
+ });
2712
+ return Promise.resolve(_temp && _temp.then ? _temp.then(function () {}) : void 0);
2713
+ } catch (e) {
2714
+ return Promise.reject(e);
2715
+ }
2716
+ }, timeoutMS);
2717
+ });
2718
+ }
2719
+
2720
+ var AxiosAdapter = /*#__PURE__*/function () {
2721
+ function AxiosAdapter() {}
2722
+ AxiosAdapter.call = function call(method) {
2723
+ try {
2724
+ var _arguments = arguments;
2725
+ return Promise.resolve(axios__default["default"][method].apply(axios__default["default"], [].slice.call(_arguments, 1)));
2726
+ } catch (e) {
2727
+ return Promise.reject(e);
2728
+ }
2729
+ };
2730
+ AxiosAdapter.get = function get() {
2731
+ try {
2732
+ var _arguments2 = arguments;
2733
+ return Promise.resolve(axios__default["default"].get.apply(axios__default["default"], [].slice.call(_arguments2)));
2734
+ } catch (e) {
2735
+ return Promise.reject(e);
2736
+ }
2737
+ };
2738
+ AxiosAdapter.post = function post() {
2739
+ try {
2740
+ var _arguments3 = arguments;
2741
+ return Promise.resolve(axios__default["default"].post.apply(axios__default["default"], [].slice.call(_arguments3)));
2742
+ } catch (e) {
2743
+ return Promise.reject(e);
2744
+ }
2745
+ };
2746
+ AxiosAdapter.put = function put() {
2747
+ try {
2748
+ var _arguments4 = arguments;
2749
+ return Promise.resolve(axios__default["default"].put.apply(axios__default["default"], [].slice.call(_arguments4)));
2750
+ } catch (e) {
2751
+ return Promise.reject(e);
2752
+ }
2753
+ };
2754
+ AxiosAdapter["delete"] = function _delete() {
2755
+ try {
2756
+ var _arguments5 = arguments;
2757
+ return Promise.resolve(axios__default["default"]["delete"].apply(axios__default["default"], [].slice.call(_arguments5)));
2758
+ } catch (e) {
2759
+ return Promise.reject(e);
2760
+ }
2761
+ };
2762
+ AxiosAdapter.patch = function patch() {
2763
+ try {
2764
+ var _arguments6 = arguments;
2765
+ return Promise.resolve(axios__default["default"].patch.apply(axios__default["default"], [].slice.call(_arguments6)));
2766
+ } catch (e) {
2767
+ return Promise.reject(e);
2768
+ }
2769
+ };
2770
+ AxiosAdapter.options = function options() {
2771
+ try {
2772
+ var _arguments7 = arguments;
2773
+ return Promise.resolve(axios__default["default"].options.apply(axios__default["default"], [].slice.call(_arguments7)));
2774
+ } catch (e) {
2775
+ return Promise.reject(e);
2776
+ }
2777
+ };
2778
+ AxiosAdapter.head = function head() {
2779
+ try {
2780
+ var _arguments8 = arguments;
2781
+ return Promise.resolve(axios__default["default"].head.apply(axios__default["default"], [].slice.call(_arguments8)));
2782
+ } catch (e) {
2783
+ return Promise.reject(e);
2784
+ }
2785
+ };
2786
+ return AxiosAdapter;
2787
+ }();
2788
+
2789
+ function _catch$6(body, recover) {
2584
2790
  try {
2585
2791
  var result = body();
2586
2792
  } catch (e) {
@@ -2596,7 +2802,7 @@ var EmailsApi = /*#__PURE__*/function () {
2596
2802
  EmailsApi.sendEmail = function sendEmail(subject, body) {
2597
2803
  try {
2598
2804
  var _this = this;
2599
- var _temp = _catch$3(function () {
2805
+ var _temp = _catch$6(function () {
2600
2806
  var url = window.location.protocol + "//" + window.location.host + "/api/v1/" + _this.serverEndpointEntity;
2601
2807
  return Promise.resolve(axios__default["default"].post(url, {
2602
2808
  subject: subject,
@@ -2614,6 +2820,1825 @@ var EmailsApi = /*#__PURE__*/function () {
2614
2820
  }();
2615
2821
  EmailsApi.serverEndpointEntity = "emails";
2616
2822
 
2823
+ /**
2824
+ * This util helps to avoid duplicated calls to a shared resource.
2825
+ * It tracks is there currently active calculation for the specific cache id and make all other requests
2826
+ * with the same cache id waiting for this active calculation to be finished. When the calculation ends
2827
+ * the resolver allows all the waiting requesters to get the data from cache and start their own calculations.
2828
+ *
2829
+ * This class should be instantiated inside some other service where you need to request some resource concurrently.
2830
+ * Rules:
2831
+ * 1. When you need to make a request inside your main service call 'getCachedOrWaitForCachedOrAcquireLock'
2832
+ * on the instance of this class and await for the result. If the flag allowing to start calculation is true
2833
+ * then you can request data inside your main service. Otherwise you should use the cached data as an another
2834
+ * requester just finished the most resent requesting and there is actual data in the cache that
2835
+ * is returned to you here.
2836
+ * 1.1 Also you can acquire a lock directly if you don't want to get cached data. Use the corresponding method 'acquireLock'.
2837
+ *
2838
+ * 2. If you start requesting (when you successfully acquired the lock) then after receiving the result of your
2839
+ * requesting you should call the 'saveCachedData' so the retrieved data will appear in the cache.
2840
+ *
2841
+ * 3. If you successfully acquired the lock then you should after calling the 'saveCachedData' call
2842
+ * the 'releaseLock' - this is mandatory to release the lock and allow other requesters to perform their requests.
2843
+ * WARNING: If for any reason you forget to call this method then this class instance will wait perpetually for
2844
+ * the lock releasing and all your attempts to request the data will constantly fail. So usually call it
2845
+ * inside the 'finally' block.
2846
+ *
2847
+ * TODO: [tests, critical++] add unit tests - massively used logic and can produce sophisticated concurrency bugs
2848
+ */
2849
+
2850
+ function _settle$2(pact, state, value) {
2851
+ if (!pact.s) {
2852
+ if (value instanceof _Pact$2) {
2853
+ if (value.s) {
2854
+ if (state & 1) {
2855
+ state = value.s;
2856
+ }
2857
+ value = value.v;
2858
+ } else {
2859
+ value.o = _settle$2.bind(null, pact, state);
2860
+ return;
2861
+ }
2862
+ }
2863
+ if (value && value.then) {
2864
+ value.then(_settle$2.bind(null, pact, state), _settle$2.bind(null, pact, 2));
2865
+ return;
2866
+ }
2867
+ pact.s = state;
2868
+ pact.v = value;
2869
+ const observer = pact.o;
2870
+ if (observer) {
2871
+ observer(pact);
2872
+ }
2873
+ }
2874
+ }
2875
+
2876
+ /**
2877
+ * Util class to control access to a resource when it can be called in parallel for the same result.
2878
+ * (E.g. getting today coins-fiat rates from some API).
2879
+ */
2880
+ var _Pact$2 = /*#__PURE__*/function () {
2881
+ function _Pact() {}
2882
+ _Pact.prototype.then = function (onFulfilled, onRejected) {
2883
+ var result = new _Pact();
2884
+ var state = this.s;
2885
+ if (state) {
2886
+ var callback = state & 1 ? onFulfilled : onRejected;
2887
+ if (callback) {
2888
+ try {
2889
+ _settle$2(result, 1, callback(this.v));
2890
+ } catch (e) {
2891
+ _settle$2(result, 2, e);
2892
+ }
2893
+ return result;
2894
+ } else {
2895
+ return this;
2896
+ }
2897
+ }
2898
+ this.o = function (_this) {
2899
+ try {
2900
+ var value = _this.v;
2901
+ if (_this.s & 1) {
2902
+ _settle$2(result, 1, onFulfilled ? onFulfilled(value) : value);
2903
+ } else if (onRejected) {
2904
+ _settle$2(result, 1, onRejected(value));
2905
+ } else {
2906
+ _settle$2(result, 2, value);
2907
+ }
2908
+ } catch (e) {
2909
+ _settle$2(result, 2, e);
2910
+ }
2911
+ };
2912
+ return result;
2913
+ };
2914
+ return _Pact;
2915
+ }();
2916
+ function _isSettledPact$2(thenable) {
2917
+ return thenable instanceof _Pact$2 && thenable.s & 1;
2918
+ }
2919
+ function _for$1(test, update, body) {
2920
+ var stage;
2921
+ for (;;) {
2922
+ var shouldContinue = test();
2923
+ if (_isSettledPact$2(shouldContinue)) {
2924
+ shouldContinue = shouldContinue.v;
2925
+ }
2926
+ if (!shouldContinue) {
2927
+ return result;
2928
+ }
2929
+ if (shouldContinue.then) {
2930
+ stage = 0;
2931
+ break;
2932
+ }
2933
+ var result = body();
2934
+ if (result && result.then) {
2935
+ if (_isSettledPact$2(result)) {
2936
+ result = result.s;
2937
+ } else {
2938
+ stage = 1;
2939
+ break;
2940
+ }
2941
+ }
2942
+ if (update) {
2943
+ var updateValue = update();
2944
+ if (updateValue && updateValue.then && !_isSettledPact$2(updateValue)) {
2945
+ stage = 2;
2946
+ break;
2947
+ }
2948
+ }
2949
+ }
2950
+ var pact = new _Pact$2();
2951
+ var reject = _settle$2.bind(null, pact, 2);
2952
+ (stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
2953
+ return pact;
2954
+ function _resumeAfterBody(value) {
2955
+ result = value;
2956
+ do {
2957
+ if (update) {
2958
+ updateValue = update();
2959
+ if (updateValue && updateValue.then && !_isSettledPact$2(updateValue)) {
2960
+ updateValue.then(_resumeAfterUpdate).then(void 0, reject);
2961
+ return;
2962
+ }
2963
+ }
2964
+ shouldContinue = test();
2965
+ if (!shouldContinue || _isSettledPact$2(shouldContinue) && !shouldContinue.v) {
2966
+ _settle$2(pact, 1, result);
2967
+ return;
2968
+ }
2969
+ if (shouldContinue.then) {
2970
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
2971
+ return;
2972
+ }
2973
+ result = body();
2974
+ if (_isSettledPact$2(result)) {
2975
+ result = result.v;
2976
+ }
2977
+ } while (!result || !result.then);
2978
+ result.then(_resumeAfterBody).then(void 0, reject);
2979
+ }
2980
+ function _resumeAfterTest(shouldContinue) {
2981
+ if (shouldContinue) {
2982
+ result = body();
2983
+ if (result && result.then) {
2984
+ result.then(_resumeAfterBody).then(void 0, reject);
2985
+ } else {
2986
+ _resumeAfterBody(result);
2987
+ }
2988
+ } else {
2989
+ _settle$2(pact, 1, result);
2990
+ }
2991
+ }
2992
+ function _resumeAfterUpdate() {
2993
+ if (shouldContinue = test()) {
2994
+ if (shouldContinue.then) {
2995
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
2996
+ } else {
2997
+ _resumeAfterTest(shouldContinue);
2998
+ }
2999
+ } else {
3000
+ _settle$2(pact, 1, result);
3001
+ }
3002
+ }
3003
+ }
3004
+ function _catch$5(body, recover) {
3005
+ try {
3006
+ var result = body();
3007
+ } catch (e) {
3008
+ return recover(e);
3009
+ }
3010
+ if (result && result.then) {
3011
+ return result.then(void 0, recover);
3012
+ }
3013
+ return result;
3014
+ }
3015
+ var CacheAndConcurrentRequestsResolver = /*#__PURE__*/function () {
3016
+ /**
3017
+ * @param bio {string} unique identifier for the exact service
3018
+ * @param cache {Cache} cache
3019
+ * @param cacheTtl {number|null} time to live for cache ms. 0 or null means the cache cannot expire
3020
+ * @param [maxCallAttemptsToWaitForAlreadyRunningRequest=100] {number} number of request allowed to do waiting for
3021
+ * result before we fail the original request. Use custom value only if you need to make the attempts count
3022
+ * and polling interval changes.
3023
+ * @param [timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished=1000] {number}
3024
+ * timeout ms for polling for a result. if you change maxCallAttemptsToWaitForAlreadyRunningRequest
3025
+ * then this parameter maybe also require the custom value.
3026
+ * @param [removeExpiredCacheAutomatically=true] {boolean}
3027
+ */
3028
+ function CacheAndConcurrentRequestsResolver(bio, cache, cacheTtl, removeExpiredCacheAutomatically, maxCallAttemptsToWaitForAlreadyRunningRequest, timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished) {
3029
+ if (removeExpiredCacheAutomatically === void 0) {
3030
+ removeExpiredCacheAutomatically = true;
3031
+ }
3032
+ if (maxCallAttemptsToWaitForAlreadyRunningRequest === void 0) {
3033
+ maxCallAttemptsToWaitForAlreadyRunningRequest = 100;
3034
+ }
3035
+ if (timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished === void 0) {
3036
+ timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished = 1000;
3037
+ }
3038
+ if (cacheTtl != null && cacheTtl < timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished * 2) {
3039
+ /*
3040
+ * During the lifetime of this service e.g. if the data is being retrieved slowly we can get
3041
+ * RACE CONDITION when we constantly retrieve data and during retrieval it is expired, so we are trying
3042
+ * to retrieve it again and again.
3043
+ * We have a protection mechanism that we will wait no more than
3044
+ * maxCallAttemptsToWaitForAlreadyRunningRequest * timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished
3045
+ * but this additional check is aimed to reduce potential loading time for some requests.
3046
+ */
3047
+ throw new Error("DEV: Wrong parameters passed to construct " + bio + " - TTL " + cacheTtl + " should be 2 times greater than " + timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished);
3048
+ }
3049
+ this._bio = bio;
3050
+ this._cache = cache;
3051
+ this._cacheTtlMs = cacheTtl != null ? cacheTtl : null;
3052
+ this._maxExecutionTimeMs = maxCallAttemptsToWaitForAlreadyRunningRequest * timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished;
3053
+ this._removeExpiredCacheAutomatically = removeExpiredCacheAutomatically;
3054
+ this._requestsManager = new ManagerOfRequestsToTheSameResource(bio, maxCallAttemptsToWaitForAlreadyRunningRequest, timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished);
3055
+ }
3056
+
3057
+ /**
3058
+ * When using this service this is the major method you should call to get data by cache id.
3059
+ * This method checks is there cached data and ether
3060
+ * - returns you flag that you can start requesting data from the shared resource
3061
+ * - or if there is already started calculation waits until it is finished (removed from this service)
3062
+ * and returns you the retrieved data
3063
+ * - or just returns you the cached data
3064
+ *
3065
+ * 'canStartDataRetrieval' equal true means that the lock was acquired, and you should manually call 'saveCachedData'
3066
+ * if needed and then 'releaseLock' to mark this calculation as finished so other
3067
+ * requesters can take their share of the resource.
3068
+ *
3069
+ * @param cacheId {string}
3070
+ * @return {Promise<({
3071
+ * canStartDataRetrieval: true,
3072
+ * cachedData: any,
3073
+ * lockId: string
3074
+ * }|{
3075
+ * canStartDataRetrieval: false,
3076
+ * cachedData: any
3077
+ * })>}
3078
+ */
3079
+ var _proto = CacheAndConcurrentRequestsResolver.prototype;
3080
+ _proto.getCachedOrWaitForCachedOrAcquireLock = function getCachedOrWaitForCachedOrAcquireLock(cacheId) {
3081
+ try {
3082
+ var _this = this;
3083
+ return Promise.resolve(_catch$5(function () {
3084
+ function _temp2() {
3085
+ var _cached, _cached2;
3086
+ return calculationId ? {
3087
+ canStartDataRetrieval: true,
3088
+ cachedData: (_cached = cached) != null ? _cached : cachedDataBackupIsPresentButExpired,
3089
+ lockId: calculationId
3090
+ } : {
3091
+ canStartDataRetrieval: false,
3092
+ cachedData: (_cached2 = cached) != null ? _cached2 : cachedDataBackupIsPresentButExpired
3093
+ };
3094
+ }
3095
+ var startedAtTimestamp = Date.now();
3096
+ var cached = _this._cache.get(cacheId);
3097
+ var cachedDataBackupIsPresentButExpired = null;
3098
+ if (cached != null && !_this._removeExpiredCacheAutomatically) {
3099
+ var lastUpdateTimestamp = _this._cache.getLastUpdateTimestamp(cacheId);
3100
+ if ((lastUpdateTimestamp != null ? lastUpdateTimestamp : 0) + _this._cacheTtlMs < Date.now()) {
3101
+ /*
3102
+ * Here we are manually clearing 'cached' value retrieved from cache to force the data loading.
3103
+ * But we save its value first to the backup variable to be able to return this value if ongoing
3104
+ * requesting fails.
3105
+ */
3106
+ cachedDataBackupIsPresentButExpired = cached;
3107
+ cached = null;
3108
+ }
3109
+ }
3110
+ var calculationId = null;
3111
+ var isRetrievedCacheExpired = true;
3112
+ var isWaitingForActiveCalculationSucceeded;
3113
+ var weStillHaveSomeTimeToProceedExecution = true;
3114
+ var _temp = _for$1(function () {
3115
+ return calculationId == null && cached == null && !!isRetrievedCacheExpired && !!weStillHaveSomeTimeToProceedExecution;
3116
+ }, void 0, function () {
3117
+ return Promise.resolve(_this._requestsManager.startCalculationOrWaitForActiveToFinish(cacheId)).then(function (result) {
3118
+ calculationId = typeof result === "string" ? result : null;
3119
+ isWaitingForActiveCalculationSucceeded = typeof result === "boolean" ? result : null;
3120
+ cached = _this._cache.get(cacheId);
3121
+ isRetrievedCacheExpired = isWaitingForActiveCalculationSucceeded && cached == null;
3122
+ weStillHaveSomeTimeToProceedExecution = Date.now() - startedAtTimestamp < _this._maxExecutionTimeMs;
3123
+ });
3124
+ });
3125
+ return _temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp);
3126
+ }, function (e) {
3127
+ improveAndRethrow(e, _this._bio + ".getCachedOrWaitForCachedOrAcquireLock");
3128
+ }));
3129
+ } catch (e) {
3130
+ return Promise.reject(e);
3131
+ }
3132
+ }
3133
+ /**
3134
+ * Returns just the current cache value for the given id.
3135
+ * Doesn't wait for the active calculation, doesn't acquire lock, just retrieves the current cache as it is.
3136
+ *
3137
+ * @param cacheId {string}
3138
+ * @return {any}
3139
+ */
3140
+ ;
3141
+ _proto.getCached = function getCached(cacheId) {
3142
+ try {
3143
+ return this._cache.get(cacheId);
3144
+ } catch (e) {
3145
+ improveAndRethrow(e, "getCached");
3146
+ }
3147
+ };
3148
+ _proto._getTtl = function _getTtl() {
3149
+ return this._removeExpiredCacheAutomatically ? this._cacheTtlMs : null;
3150
+ }
3151
+
3152
+ /**
3153
+ * Directly acquires the lock despite on cached data availability.
3154
+ * So if this method returns result === true you can start the data retrieval.
3155
+ *
3156
+ * @param cacheId {string}
3157
+ * @return {Promise<{ result: true, lockId: string }|{ result: false }>}
3158
+ */;
3159
+ _proto.acquireLock = function acquireLock(cacheId) {
3160
+ try {
3161
+ var _this2 = this;
3162
+ return Promise.resolve(_catch$5(function () {
3163
+ return Promise.resolve(_this2._requestsManager.acquireLock(cacheId));
3164
+ }, function (e) {
3165
+ improveAndRethrow(e, "acquireLock");
3166
+ }));
3167
+ } catch (e) {
3168
+ return Promise.reject(e);
3169
+ }
3170
+ }
3171
+ /**
3172
+ * This method should be called only if you acquired a lock successfully.
3173
+ *
3174
+ * If the current lock id is not equal to the passed one the passed data will be ignored.
3175
+ * Or you can do the synchronous data merging on your side and pass the
3176
+ * wasDataMergedSynchronouslyWithMostRecentCacheState=true so your data will be stored
3177
+ * despite on the lockId.
3178
+ * WARNING: you should do this only if you are sure you perform the synchronous update.
3179
+ *
3180
+ * @param cacheId {string}
3181
+ * @param lockId {string}
3182
+ * @param data {any}
3183
+ * @param [sessionDependentData=true] {boolean}
3184
+ * @param [wasDataMergedSynchronouslyWithMostRecentCacheState=false]
3185
+ */
3186
+ ;
3187
+ _proto.saveCachedData = function saveCachedData(cacheId, lockId, data, sessionDependentData, wasDataMergedSynchronouslyWithMostRecentCacheState) {
3188
+ if (sessionDependentData === void 0) {
3189
+ sessionDependentData = true;
3190
+ }
3191
+ if (wasDataMergedSynchronouslyWithMostRecentCacheState === void 0) {
3192
+ wasDataMergedSynchronouslyWithMostRecentCacheState = false;
3193
+ }
3194
+ try {
3195
+ if (wasDataMergedSynchronouslyWithMostRecentCacheState || this._requestsManager.isTheLockActiveOne(cacheId, lockId)) {
3196
+ /* We save passed data only if the <caller> has the currently acquired lockId.
3197
+ * If the passed lockId is not the active one it means that other code cleared/stopped the lock
3198
+ * acquired by the <caller> recently due to some urgent/more prior changes.
3199
+ *
3200
+ * But we allow user to pass the 'wasDataMergedSynchronouslyWithMostRecentCacheState' flag
3201
+ * that tells us that the user had taken the most recent cache value and merged his new data
3202
+ * with that cached value (AFTER possibly performing async data retrieval). This means that we
3203
+ * can ignore the fact that his lockId is no more relevant and save the passed data
3204
+ * as it is synchronously merged with the most recent cached data. (Synchronously merged means that
3205
+ * the lost update cannot occur during the merge time as JS execute the synchronous functions\
3206
+ * till the end).
3207
+ */
3208
+ if (sessionDependentData) {
3209
+ this._cache.putSessionDependentData(cacheId, data, this._getTtl());
3210
+ } else {
3211
+ this._cache.put(cacheId, data, this._getTtl());
3212
+ }
3213
+ }
3214
+ } catch (e) {
3215
+ improveAndRethrow(e, this._bio + ".saveCachedData");
3216
+ }
3217
+ }
3218
+
3219
+ /**
3220
+ * Should be called then and only then if you successfully acquired a lock with the lock id.
3221
+ *
3222
+ * @param cacheId {string}
3223
+ * @param lockId {string}
3224
+ */;
3225
+ _proto.releaseLock = function releaseLock(cacheId, lockId) {
3226
+ try {
3227
+ if (this._requestsManager.isTheLockActiveOne(cacheId, lockId)) {
3228
+ this._requestsManager.finishActiveCalculation(cacheId);
3229
+ }
3230
+ } catch (e) {
3231
+ improveAndRethrow(e, this._bio + ".releaseLock");
3232
+ }
3233
+ }
3234
+
3235
+ /**
3236
+ * Actualized currently present cached data by key. Applies the provided function to the cached data.
3237
+ *
3238
+ * @param cacheId {string} id of cache entry
3239
+ * @param synchronousCurrentCacheProcessor (function|null} synchronous function accepting cache entry. Should return
3240
+ * an object in following format:
3241
+ * {
3242
+ * isModified: boolean,
3243
+ * data: any
3244
+ * }
3245
+ * the flag signals whether data was changed during the processing or not
3246
+ * @param [sessionDependent=true] {boolean} whether to mark the cache entry as session-dependent
3247
+ */;
3248
+ _proto.actualizeCachedData = function actualizeCachedData(cacheId, synchronousCurrentCacheProcessor, sessionDependent) {
3249
+ if (sessionDependent === void 0) {
3250
+ sessionDependent = true;
3251
+ }
3252
+ try {
3253
+ var cached = this._cache.get(cacheId);
3254
+ var result = synchronousCurrentCacheProcessor(cached);
3255
+ if (result != null && result.isModified && (result == null ? void 0 : result.data) != null) {
3256
+ if (sessionDependent) {
3257
+ this._cache.putSessionDependentData(cacheId, result == null ? void 0 : result.data, this._getTtl());
3258
+ } else {
3259
+ this._cache.put(cacheId, result == null ? void 0 : result.data, this._getTtl());
3260
+ }
3261
+
3262
+ /* Here we call the lock releasing to ensure the currently active calculation will be ignored.
3263
+ * This is needed to ensure no 'lost update'.
3264
+ * Lost update can occur if we change data in this method and after that some calculation finishes
3265
+ * having the earlier data as its base to calculate its data set result. And the earlier data
3266
+ * has no changes applied inside this method, so we will lose them.
3267
+ *
3268
+ * This is not so good solution: ideally, we should acquire lock before performing any data updating.
3269
+ * But the goal of this method is to provide an instant ability to update the cached data.
3270
+ * And if we start acquiring the lock here the data update can be postponed significantly.
3271
+ * And this kills the desired nature of this method.
3272
+ * So we better lose some data retrieval (means abusing the resource a bit) than lose
3273
+ * the instant update expected after this method execution.
3274
+ */
3275
+ this._requestsManager.finishActiveCalculation(cacheId);
3276
+ }
3277
+ } catch (e) {
3278
+ improveAndRethrow(e, this._bio + ".actualizeCachedData");
3279
+ }
3280
+ };
3281
+ _proto.invalidate = function invalidate(key) {
3282
+ this._cache.invalidate(key);
3283
+ this._requestsManager.finishActiveCalculation(key);
3284
+ };
3285
+ _proto.invalidateContaining = function invalidateContaining(keyPart) {
3286
+ this._cache.invalidateContaining(keyPart);
3287
+ this._requestsManager.finishAllActiveCalculations(keyPart);
3288
+ };
3289
+ _proto.markAsExpiredButDontRemove = function markAsExpiredButDontRemove(key) {
3290
+ if (this._removeExpiredCacheAutomatically) {
3291
+ this._cache.markCacheItemAsExpiredButDontRemove(key, this._cacheTtlMs);
3292
+ } else {
3293
+ this._cache.setLastUpdateTimestamp(key, Date.now() - this._cacheTtlMs - 1);
3294
+ }
3295
+ this._requestsManager.finishAllActiveCalculations(key);
3296
+ };
3297
+ return CacheAndConcurrentRequestsResolver;
3298
+ }();
3299
+ var ManagerOfRequestsToTheSameResource = /*#__PURE__*/function () {
3300
+ /**
3301
+ * @param bio {string} resource-related identifier for logging
3302
+ * @param [maxPollsCount=100] {number} max number of attempts to wait when waiting for a lock acquisition
3303
+ * @param [timeoutDuration=1000] {number} timeout between the polls for a lock acquisition
3304
+ */
3305
+ function ManagerOfRequestsToTheSameResource(bio, maxPollsCount, timeoutDuration) {
3306
+ if (maxPollsCount === void 0) {
3307
+ maxPollsCount = 100;
3308
+ }
3309
+ if (timeoutDuration === void 0) {
3310
+ timeoutDuration = 1000;
3311
+ }
3312
+ this.bio = bio;
3313
+ this.maxPollsCount = maxPollsCount;
3314
+ this.timeoutDuration = timeoutDuration;
3315
+ this._activeCalculationsIds = new Map();
3316
+ this._nextCalculationIds = new Map();
3317
+ }
3318
+
3319
+ /**
3320
+ * If there is no active calculation just creates uuid and returns it.
3321
+ * If there is active calculation waits until it removed from the active calculation uuid variable.
3322
+ *
3323
+ * @param requestHash {string}
3324
+ * @return {Promise<string|boolean>} returns uuid of new active calculation or true if waiting for active
3325
+ * calculation succeed or false if max attempts count exceeded
3326
+ */
3327
+ var _proto2 = ManagerOfRequestsToTheSameResource.prototype;
3328
+ _proto2.startCalculationOrWaitForActiveToFinish = function startCalculationOrWaitForActiveToFinish(requestHash) {
3329
+ try {
3330
+ var _exit;
3331
+ var _this3 = this;
3332
+ var _temp3 = _catch$5(function () {
3333
+ var activeCalculationIdForHash = _this3._activeCalculationsIds.get(requestHash);
3334
+ if (activeCalculationIdForHash == null) {
3335
+ var id = uuid.v4();
3336
+ _this3._activeCalculationsIds.set(requestHash, id);
3337
+ _exit = 1;
3338
+ return id;
3339
+ }
3340
+ return Promise.resolve(_this3._waitForCalculationIdToFinish(requestHash, activeCalculationIdForHash, 0)).then(function (_await$_this3$_waitFo) {
3341
+ _exit = 1;
3342
+ return _await$_this3$_waitFo;
3343
+ });
3344
+ }, function (e) {
3345
+ Logger.logError(e, "startCalculationOrWaitForActiveToFinish_" + _this3.bio);
3346
+ });
3347
+ return Promise.resolve(_temp3 && _temp3.then ? _temp3.then(function (_result3) {
3348
+ return _exit ? _result3 : null;
3349
+ }) : _exit ? _temp3 : null);
3350
+ } catch (e) {
3351
+ return Promise.reject(e);
3352
+ }
3353
+ }
3354
+ /**
3355
+ * Acquires lock to the resource by the provided hash.
3356
+ *
3357
+ * @param requestHash {string}
3358
+ * @return {Promise<{ result: true, lockId: string }|{ result: false }>} result is true if the lock is successfully
3359
+ * acquired, false if the max allowed time to wait for acquisition expired or any unexpected error occurs
3360
+ * during the waiting.
3361
+ */
3362
+ ;
3363
+ _proto2.acquireLock = function acquireLock(requestHash) {
3364
+ try {
3365
+ var _this4 = this;
3366
+ return Promise.resolve(_catch$5(function () {
3367
+ var _this4$_nextCalculati;
3368
+ var activeId = _this4._activeCalculationsIds.get(requestHash);
3369
+ var nextId = uuid.v4();
3370
+ if (activeId == null) {
3371
+ _this4._activeCalculationsIds.set(requestHash, nextId);
3372
+ return {
3373
+ result: true,
3374
+ lockId: nextId
3375
+ };
3376
+ }
3377
+ var currentNext = (_this4$_nextCalculati = _this4._nextCalculationIds.get(requestHash)) != null ? _this4$_nextCalculati : [];
3378
+ currentNext.push(nextId);
3379
+ _this4._nextCalculationIds.set(requestHash, currentNext);
3380
+ return Promise.resolve(_this4._waitForCalculationIdToFinish(requestHash, activeId, 0, nextId)).then(function (waitingResult) {
3381
+ return {
3382
+ result: waitingResult,
3383
+ lockId: waitingResult ? nextId : undefined
3384
+ };
3385
+ });
3386
+ }, function (e) {
3387
+ improveAndRethrow(e, "acquireLock");
3388
+ }));
3389
+ } catch (e) {
3390
+ return Promise.reject(e);
3391
+ }
3392
+ }
3393
+ /**
3394
+ * Clears active calculation id.
3395
+ * WARNING: if you forget to call this method the start* one will perform maxPollsCount attempts before finishing
3396
+ * @param requestHash {string} hash of request. Helps to distinct the request for the same resource but
3397
+ * having different request parameters and hold a dedicated calculation id per this hash
3398
+ */
3399
+ ;
3400
+ _proto2.finishActiveCalculation = function finishActiveCalculation(requestHash) {
3401
+ if (requestHash === void 0) {
3402
+ requestHash = "default";
3403
+ }
3404
+ try {
3405
+ var _this$_nextCalculatio;
3406
+ this._activeCalculationsIds["delete"](requestHash);
3407
+ var next = (_this$_nextCalculatio = this._nextCalculationIds.get(requestHash)) != null ? _this$_nextCalculatio : [];
3408
+ if (next.length) {
3409
+ this._activeCalculationsIds.set(requestHash, next[0]);
3410
+ this._nextCalculationIds.set(requestHash, next.slice(1));
3411
+ }
3412
+ } catch (e) {
3413
+ improveAndRethrow(e, "finishActiveCalculation");
3414
+ }
3415
+ };
3416
+ _proto2.finishAllActiveCalculations = function finishAllActiveCalculations(keyPart) {
3417
+ var _this5 = this;
3418
+ if (keyPart === void 0) {
3419
+ keyPart = "";
3420
+ }
3421
+ try {
3422
+ Array.from(this._activeCalculationsIds.keys()).forEach(function (hash) {
3423
+ if (typeof hash === "string" && new RegExp(keyPart).test(hash)) {
3424
+ _this5.finishActiveCalculation(hash);
3425
+ }
3426
+ });
3427
+ } catch (e) {
3428
+ improveAndRethrow(e, "finishAllActiveCalculations");
3429
+ }
3430
+ }
3431
+
3432
+ /**
3433
+ * @param requestHash {string}
3434
+ * @param lockId {string}
3435
+ * @return {boolean}
3436
+ */;
3437
+ _proto2.isTheLockActiveOne = function isTheLockActiveOne(requestHash, lockId) {
3438
+ try {
3439
+ return this._activeCalculationsIds.get(requestHash) === lockId;
3440
+ } catch (e) {
3441
+ improveAndRethrow(e, "isTheLockActiveOne");
3442
+ }
3443
+ }
3444
+
3445
+ /**
3446
+ * @param requestHash {string}
3447
+ * @param activeCalculationId {string|null}
3448
+ * @param [attemptIndex=0] {number}
3449
+ * @param waitForCalculationId {string|null} if you want to wait for an exact id to appear as active then pass this parameter
3450
+ * @return {Promise<boolean>} true
3451
+ * - if the given calculation id is no more an active one
3452
+ * - or it is equal to waitForCalculationId
3453
+ * false
3454
+ * - if waiting period exceeds the max allowed waiting time or unexpected error occurs
3455
+ * @private
3456
+ */;
3457
+ _proto2._waitForCalculationIdToFinish = function _waitForCalculationIdToFinish(requestHash, activeCalculationId, attemptIndex, waitForCalculationId) {
3458
+ if (attemptIndex === void 0) {
3459
+ attemptIndex = 0;
3460
+ }
3461
+ if (waitForCalculationId === void 0) {
3462
+ waitForCalculationId = null;
3463
+ }
3464
+ try {
3465
+ var _this6 = this;
3466
+ try {
3467
+ if (attemptIndex + 1 > _this6.maxPollsCount) {
3468
+ // Max number of polls for active calculation id change is achieved. So we return false.
3469
+ return Promise.resolve(false);
3470
+ }
3471
+ var currentId = _this6._activeCalculationsIds.get(requestHash);
3472
+ if (waitForCalculationId == null ? currentId !== activeCalculationId : currentId === waitForCalculationId) {
3473
+ /* We return true depending on the usage of this function:
3474
+ * 1. if there is calculation id that we should wait for to become an active then we return true only
3475
+ * if this id becomes the active one.
3476
+ *
3477
+ * Theoretically we can fail to wait for the desired calculation id. This can be caused by wrong use of
3478
+ * this service or by any other mistakes/errors. But this waiting function will return false anyway if
3479
+ * the number of polls done exceeds the max allowed.
3480
+ *
3481
+ * 2. if we just wait for the currently active calculation id to be finished then we return true
3482
+ * when we notice that the current active id differs from the original passed into this function.
3483
+ */
3484
+ return Promise.resolve(true);
3485
+ } else {
3486
+ /* The original calculation id is still the active one, so we are scheduling a new attempt to check
3487
+ * whether the active calculation id changed or not in timeoutDuration milliseconds.
3488
+ */
3489
+ var it = _this6;
3490
+ return Promise.resolve(new Promise(function (resolve, reject) {
3491
+ setTimeout(function () {
3492
+ try {
3493
+ resolve(it._waitForCalculationIdToFinish(requestHash, activeCalculationId, attemptIndex + 1));
3494
+ } catch (e) {
3495
+ reject(e);
3496
+ }
3497
+ }, _this6.timeoutDuration);
3498
+ }));
3499
+ }
3500
+ } catch (e) {
3501
+ Logger.logError(e, "_waitForCalculationIdToFinish", "Failed to wait for active calculation id change.");
3502
+ return Promise.resolve(false);
3503
+ }
3504
+ } catch (e) {
3505
+ return Promise.reject(e);
3506
+ }
3507
+ };
3508
+ return ManagerOfRequestsToTheSameResource;
3509
+ }();
3510
+
3511
+ // TODO: [refactoring, low] Consider removing this logic task_id=c360f2af75764bde8badd9ff1cc00d48
3512
+ var ConcurrentCalculationsMetadataHolder = /*#__PURE__*/function () {
3513
+ function ConcurrentCalculationsMetadataHolder() {
3514
+ this._calculations = {};
3515
+ }
3516
+ var _proto = ConcurrentCalculationsMetadataHolder.prototype;
3517
+ _proto.startCalculation = function startCalculation(domain, calculationsHistoryMaxLength) {
3518
+ if (calculationsHistoryMaxLength === void 0) {
3519
+ calculationsHistoryMaxLength = 100;
3520
+ }
3521
+ if (!this._calculations[domain]) {
3522
+ this._calculations[domain] = [];
3523
+ }
3524
+ if (this._calculations[domain].length > calculationsHistoryMaxLength) {
3525
+ this._calculations[domain] = this._calculations[domain].slice(Math.round(calculationsHistoryMaxLength * 0.2));
3526
+ }
3527
+ var newCalculation = {
3528
+ startTimestamp: Date.now(),
3529
+ endTimestamp: null,
3530
+ uuid: uuid.v4()
3531
+ };
3532
+ this._calculations[domain].push(newCalculation);
3533
+ return newCalculation.uuid;
3534
+ };
3535
+ _proto.endCalculation = function endCalculation(domain, uuid, isFailed) {
3536
+ if (isFailed === void 0) {
3537
+ isFailed = false;
3538
+ }
3539
+ try {
3540
+ var _calculation$endTimes, _calculation$startTim, _calculation$uuid;
3541
+ var calculation = this._calculations[domain].find(function (calculation) {
3542
+ return (calculation == null ? void 0 : calculation.uuid) === uuid;
3543
+ });
3544
+ if (calculation) {
3545
+ calculation.endTimestamp = Date.now();
3546
+ calculation.isFiled = isFailed;
3547
+ }
3548
+ var elapsed = ((((_calculation$endTimes = calculation == null ? void 0 : calculation.endTimestamp) != null ? _calculation$endTimes : 0) - ((_calculation$startTim = calculation == null ? void 0 : calculation.startTimestamp) != null ? _calculation$startTim : 0)) / 1000).toFixed(1);
3549
+ Logger.log("endCalculation", elapsed + " ms: " + domain + "." + ((_calculation$uuid = calculation == null ? void 0 : calculation.uuid) != null ? _calculation$uuid : "").slice(0, 7));
3550
+ return calculation;
3551
+ } catch (e) {
3552
+ Logger.logError(e, "endCalculation");
3553
+ }
3554
+ };
3555
+ _proto.isCalculationLate = function isCalculationLate(domain, uuid) {
3556
+ var queue = this._calculations[domain];
3557
+ var analysingCalculation = queue.find(function (item) {
3558
+ return item.uuid === uuid;
3559
+ });
3560
+ return analysingCalculation && !!queue.find(function (calculation) {
3561
+ return calculation.endTimestamp != null && calculation.startTimestamp > analysingCalculation.startTimestamp;
3562
+ });
3563
+ };
3564
+ _proto.printCalculationsWaitingMoreThanSpecifiedSeconds = function printCalculationsWaitingMoreThanSpecifiedSeconds(waitingLastsMs) {
3565
+ var _this = this;
3566
+ if (waitingLastsMs === void 0) {
3567
+ waitingLastsMs = 2000;
3568
+ }
3569
+ var calculations = Object.keys(this._calculations).map(function (domain) {
3570
+ return _this._calculations[domain].map(function (c) {
3571
+ return _extends({}, c, {
3572
+ domain: domain
3573
+ });
3574
+ });
3575
+ }).flat().filter(function (c) {
3576
+ return c.endTimestamp === null && Date.now() - c.startTimestamp > waitingLastsMs;
3577
+ });
3578
+ Logger.log("printCalculationsWaitingMoreThanSpecifiedSeconds", "Calculations waiting more than " + (waitingLastsMs / 1000).toFixed(1) + "s:\n" + calculations.map(function (c) {
3579
+ return c.domain + "." + c.uuid.slice(0, 8) + ": " + (Date.now() - c.startTimestamp) + "\n";
3580
+ }));
3581
+ };
3582
+ return ConcurrentCalculationsMetadataHolder;
3583
+ }();
3584
+ var concurrentCalculationsMetadataHolder = new ConcurrentCalculationsMetadataHolder();
3585
+
3586
+ var ExternalServicesStatsCollector = /*#__PURE__*/function () {
3587
+ function ExternalServicesStatsCollector() {
3588
+ this.stats = new Map();
3589
+ }
3590
+ var _proto = ExternalServicesStatsCollector.prototype;
3591
+ _proto.externalServiceFailed = function externalServiceFailed(serviceUrl, message) {
3592
+ try {
3593
+ var processMessage = function processMessage(stat, errorMessage) {
3594
+ var _stat$errors, _errorMessage;
3595
+ var errors = (_stat$errors = stat.errors) != null ? _stat$errors : {};
3596
+ errorMessage = (_errorMessage = errorMessage) != null ? _errorMessage : "";
3597
+ if (errorMessage.match(/.*network.+error.*/i)) {
3598
+ errors["networkError"] = (errors["networkError"] || 0) + 1;
3599
+ } else if (errorMessage.match(/.*timeout.+exceeded.*/i)) {
3600
+ errors["timeoutExceeded"] = (errors["timeoutExceeded"] || 0) + 1;
3601
+ } else if (errors["other"]) {
3602
+ errors["other"].push(message);
3603
+ } else {
3604
+ errors["other"] = [message];
3605
+ }
3606
+ stat.errors = errors;
3607
+ };
3608
+ if (this.stats.has(serviceUrl)) {
3609
+ var stat = this.stats.get(serviceUrl);
3610
+ stat.callsCount += 1;
3611
+ stat.failsCount += 1;
3612
+ processMessage(stat, message);
3613
+ } else {
3614
+ this.stats.set(serviceUrl, {
3615
+ callsCount: 1,
3616
+ failsCount: 1
3617
+ });
3618
+ processMessage(this.stats.get(serviceUrl), message);
3619
+ }
3620
+ } catch (e) {
3621
+ improveAndRethrow(e, "externalServiceFailed");
3622
+ }
3623
+ };
3624
+ _proto.externalServiceCalledWithoutError = function externalServiceCalledWithoutError(serviceUrl) {
3625
+ try {
3626
+ if (this.stats.has(serviceUrl)) {
3627
+ var stat = this.stats.get(serviceUrl);
3628
+ stat.callsCount += 1;
3629
+ } else {
3630
+ this.stats.set(serviceUrl, {
3631
+ callsCount: 1,
3632
+ failsCount: 0
3633
+ });
3634
+ }
3635
+ } catch (e) {
3636
+ improveAndRethrow(e, "externalServiceCalledWithoutError");
3637
+ }
3638
+ }
3639
+
3640
+ /**
3641
+ * Returns statistics about external services failures.
3642
+ * Provides how many calls were performed and what the percent of failed calls. Also returns errors stat.
3643
+ *
3644
+ * @return {Array<object>} Array of objects of type { failsPerCent: number, calls: number }
3645
+ * sorted by the highest fails percent desc
3646
+ */;
3647
+ _proto.getStats = function getStats() {
3648
+ var _this = this;
3649
+ try {
3650
+ return Array.from(this.stats.keys()).map(function (key) {
3651
+ var _stat$errors2;
3652
+ var stat = _this.stats.get(key);
3653
+ return {
3654
+ url: key,
3655
+ failsPerCent: (stat.failsCount / stat.callsCount * 100).toFixed(2),
3656
+ calls: stat.callsCount,
3657
+ errors: (_stat$errors2 = stat.errors) != null ? _stat$errors2 : []
3658
+ };
3659
+ }).sort(function (s1, s2) {
3660
+ return s1.failsPerCent - s2.failsPerCent;
3661
+ });
3662
+ } catch (e) {
3663
+ Logger.logError(e, "getStats");
3664
+ }
3665
+ };
3666
+ return ExternalServicesStatsCollector;
3667
+ }();
3668
+
3669
+ /**
3670
+ * TODO: [refactoring, critical] update backend copy of this service. Also there is a task to extract this
3671
+ * service and other related to it stuff to dedicated npm package task_id=b008ee5e4a3f42c08c73831c4bb3db4e
3672
+ *
3673
+ * Template service needed to avoid duplication of the same logic when we need to call
3674
+ * external APIs to retrieve some data. The idea is to use several API providers to retrieve the same data. It helps to
3675
+ * improve the reliability of a data retrieval.
3676
+ */
3677
+
3678
+ function _catch$4(body, recover) {
3679
+ try {
3680
+ var result = body();
3681
+ } catch (e) {
3682
+ return recover(e);
3683
+ }
3684
+ if (result && result.then) {
3685
+ return result.then(void 0, recover);
3686
+ }
3687
+ return result;
3688
+ }
3689
+ function _settle$1(pact, state, value) {
3690
+ if (!pact.s) {
3691
+ if (value instanceof _Pact$1) {
3692
+ if (value.s) {
3693
+ if (state & 1) {
3694
+ state = value.s;
3695
+ }
3696
+ value = value.v;
3697
+ } else {
3698
+ value.o = _settle$1.bind(null, pact, state);
3699
+ return;
3700
+ }
3701
+ }
3702
+ if (value && value.then) {
3703
+ value.then(_settle$1.bind(null, pact, state), _settle$1.bind(null, pact, 2));
3704
+ return;
3705
+ }
3706
+ pact.s = state;
3707
+ pact.v = value;
3708
+ var observer = pact.o;
3709
+ if (observer) {
3710
+ observer(pact);
3711
+ }
3712
+ }
3713
+ }
3714
+ var _Pact$1 = /*#__PURE__*/function () {
3715
+ function _Pact() {}
3716
+ _Pact.prototype.then = function (onFulfilled, onRejected) {
3717
+ var result = new _Pact();
3718
+ var state = this.s;
3719
+ if (state) {
3720
+ var callback = state & 1 ? onFulfilled : onRejected;
3721
+ if (callback) {
3722
+ try {
3723
+ _settle$1(result, 1, callback(this.v));
3724
+ } catch (e) {
3725
+ _settle$1(result, 2, e);
3726
+ }
3727
+ return result;
3728
+ } else {
3729
+ return this;
3730
+ }
3731
+ }
3732
+ this.o = function (_this) {
3733
+ try {
3734
+ var value = _this.v;
3735
+ if (_this.s & 1) {
3736
+ _settle$1(result, 1, onFulfilled ? onFulfilled(value) : value);
3737
+ } else if (onRejected) {
3738
+ _settle$1(result, 1, onRejected(value));
3739
+ } else {
3740
+ _settle$1(result, 2, value);
3741
+ }
3742
+ } catch (e) {
3743
+ _settle$1(result, 2, e);
3744
+ }
3745
+ };
3746
+ return result;
3747
+ };
3748
+ return _Pact;
3749
+ }();
3750
+ function _isSettledPact$1(thenable) {
3751
+ return thenable instanceof _Pact$1 && thenable.s & 1;
3752
+ }
3753
+ function _for(test, update, body) {
3754
+ var stage;
3755
+ for (;;) {
3756
+ var shouldContinue = test();
3757
+ if (_isSettledPact$1(shouldContinue)) {
3758
+ shouldContinue = shouldContinue.v;
3759
+ }
3760
+ if (!shouldContinue) {
3761
+ return result;
3762
+ }
3763
+ if (shouldContinue.then) {
3764
+ stage = 0;
3765
+ break;
3766
+ }
3767
+ var result = body();
3768
+ if (result && result.then) {
3769
+ if (_isSettledPact$1(result)) {
3770
+ result = result.s;
3771
+ } else {
3772
+ stage = 1;
3773
+ break;
3774
+ }
3775
+ }
3776
+ if (update) {
3777
+ var updateValue = update();
3778
+ if (updateValue && updateValue.then && !_isSettledPact$1(updateValue)) {
3779
+ stage = 2;
3780
+ break;
3781
+ }
3782
+ }
3783
+ }
3784
+ var pact = new _Pact$1();
3785
+ var reject = _settle$1.bind(null, pact, 2);
3786
+ (stage === 0 ? shouldContinue.then(_resumeAfterTest) : stage === 1 ? result.then(_resumeAfterBody) : updateValue.then(_resumeAfterUpdate)).then(void 0, reject);
3787
+ return pact;
3788
+ function _resumeAfterBody(value) {
3789
+ result = value;
3790
+ do {
3791
+ if (update) {
3792
+ updateValue = update();
3793
+ if (updateValue && updateValue.then && !_isSettledPact$1(updateValue)) {
3794
+ updateValue.then(_resumeAfterUpdate).then(void 0, reject);
3795
+ return;
3796
+ }
3797
+ }
3798
+ shouldContinue = test();
3799
+ if (!shouldContinue || _isSettledPact$1(shouldContinue) && !shouldContinue.v) {
3800
+ _settle$1(pact, 1, result);
3801
+ return;
3802
+ }
3803
+ if (shouldContinue.then) {
3804
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
3805
+ return;
3806
+ }
3807
+ result = body();
3808
+ if (_isSettledPact$1(result)) {
3809
+ result = result.v;
3810
+ }
3811
+ } while (!result || !result.then);
3812
+ result.then(_resumeAfterBody).then(void 0, reject);
3813
+ }
3814
+ function _resumeAfterTest(shouldContinue) {
3815
+ if (shouldContinue) {
3816
+ result = body();
3817
+ if (result && result.then) {
3818
+ result.then(_resumeAfterBody).then(void 0, reject);
3819
+ } else {
3820
+ _resumeAfterBody(result);
3821
+ }
3822
+ } else {
3823
+ _settle$1(pact, 1, result);
3824
+ }
3825
+ }
3826
+ function _resumeAfterUpdate() {
3827
+ if (shouldContinue = test()) {
3828
+ if (shouldContinue.then) {
3829
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
3830
+ } else {
3831
+ _resumeAfterTest(shouldContinue);
3832
+ }
3833
+ } else {
3834
+ _settle$1(pact, 1, result);
3835
+ }
3836
+ }
3837
+ }
3838
+ function _finallyRethrows$1(body, finalizer) {
3839
+ try {
3840
+ var result = body();
3841
+ } catch (e) {
3842
+ return finalizer(true, e);
3843
+ }
3844
+ if (result && result.then) {
3845
+ return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
3846
+ }
3847
+ return finalizer(false, result);
3848
+ }
3849
+ function _do(body, test) {
3850
+ var awaitBody;
3851
+ do {
3852
+ var result = body();
3853
+ if (result && result.then) {
3854
+ if (_isSettledPact$1(result)) {
3855
+ result = result.v;
3856
+ } else {
3857
+ awaitBody = true;
3858
+ break;
3859
+ }
3860
+ }
3861
+ var shouldContinue = test();
3862
+ if (_isSettledPact$1(shouldContinue)) {
3863
+ shouldContinue = shouldContinue.v;
3864
+ }
3865
+ if (!shouldContinue) {
3866
+ return result;
3867
+ }
3868
+ } while (!shouldContinue.then);
3869
+ var pact = new _Pact$1();
3870
+ var reject = _settle$1.bind(null, pact, 2);
3871
+ (awaitBody ? result.then(_resumeAfterBody) : shouldContinue.then(_resumeAfterTest)).then(void 0, reject);
3872
+ return pact;
3873
+ function _resumeAfterBody(value) {
3874
+ result = value;
3875
+ for (;;) {
3876
+ shouldContinue = test();
3877
+ if (_isSettledPact$1(shouldContinue)) {
3878
+ shouldContinue = shouldContinue.v;
3879
+ }
3880
+ if (!shouldContinue) {
3881
+ break;
3882
+ }
3883
+ if (shouldContinue.then) {
3884
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
3885
+ return;
3886
+ }
3887
+ result = body();
3888
+ if (result && result.then) {
3889
+ if (_isSettledPact$1(result)) {
3890
+ result = result.v;
3891
+ } else {
3892
+ result.then(_resumeAfterBody).then(void 0, reject);
3893
+ return;
3894
+ }
3895
+ }
3896
+ }
3897
+ _settle$1(pact, 1, result);
3898
+ }
3899
+ function _resumeAfterTest(shouldContinue) {
3900
+ if (shouldContinue) {
3901
+ do {
3902
+ result = body();
3903
+ if (result && result.then) {
3904
+ if (_isSettledPact$1(result)) {
3905
+ result = result.v;
3906
+ } else {
3907
+ result.then(_resumeAfterBody).then(void 0, reject);
3908
+ return;
3909
+ }
3910
+ }
3911
+ shouldContinue = test();
3912
+ if (_isSettledPact$1(shouldContinue)) {
3913
+ shouldContinue = shouldContinue.v;
3914
+ }
3915
+ if (!shouldContinue) {
3916
+ _settle$1(pact, 1, result);
3917
+ return;
3918
+ }
3919
+ } while (!shouldContinue.then);
3920
+ shouldContinue.then(_resumeAfterTest).then(void 0, reject);
3921
+ } else {
3922
+ _settle$1(pact, 1, result);
3923
+ }
3924
+ }
3925
+ }
3926
+ function _forTo$1(array, body, check) {
3927
+ var i = -1,
3928
+ pact,
3929
+ reject;
3930
+ function _cycle(result) {
3931
+ try {
3932
+ while (++i < array.length && (!check || !check())) {
3933
+ result = body(i);
3934
+ if (result && result.then) {
3935
+ if (_isSettledPact$1(result)) {
3936
+ result = result.v;
3937
+ } else {
3938
+ result.then(_cycle, reject || (reject = _settle$1.bind(null, pact = new _Pact$1(), 2)));
3939
+ return;
3940
+ }
3941
+ }
3942
+ }
3943
+ if (pact) {
3944
+ _settle$1(pact, 1, result);
3945
+ } else {
3946
+ pact = result;
3947
+ }
3948
+ } catch (e) {
3949
+ _settle$1(pact || (pact = new _Pact$1()), 2, e);
3950
+ }
3951
+ }
3952
+ _cycle();
3953
+ return pact;
3954
+ }
3955
+ var RobustExternalAPICallerService = /*#__PURE__*/function () {
3956
+ RobustExternalAPICallerService.getStats = function getStats() {
3957
+ this.statsCollector.getStats();
3958
+ }
3959
+
3960
+ /**
3961
+ * @param bio {string} service name for logging
3962
+ * @param providersData {ExternalApiProvider[]} array of providers
3963
+ * @param [logger] {function} function to be used for logging
3964
+ */;
3965
+ function RobustExternalAPICallerService(bio, providersData, logger) {
3966
+ providersData.forEach(function (provider) {
3967
+ if (!provider.endpoint && provider.endpoint !== "" || !provider.httpMethod) {
3968
+ throw new Error("Wrong format of providers data for: " + JSON.stringify(provider));
3969
+ }
3970
+ });
3971
+
3972
+ // We add niceFactor - just number to order the providers array by. It is helpful to call
3973
+ // less robust APIs only if more robust fails
3974
+ this.providers = providersData;
3975
+ providersData.forEach(function (provider) {
3976
+ return provider.resetNiceFactor();
3977
+ });
3978
+ this.bio = bio;
3979
+ this._logger = Logger.logError;
3980
+ }
3981
+ var _proto = RobustExternalAPICallerService.prototype;
3982
+ /**
3983
+ * Performs data retrieval from external APIs. Tries providers till the data is retrieved.
3984
+ *
3985
+ * @param parametersValues {array} array of values of the parameters for URL query string [and/or body]
3986
+ * @param timeoutMS {number} http timeout to wait for response. If provider has its specific timeout value then it is used
3987
+ * @param [cancelToken] {object|undefined} axios token to force-cancel requests from high-level code
3988
+ * @param [attemptsCount] {number|undefined} number of attempts to be performed
3989
+ * @param [doNotFailForNowData] {boolean|undefined} pass true if you do not want us to throw an error if we retrieved null data from all the providers
3990
+ * @return {Promise<any>} resolving to retrieved data (or array of results if specific provider requires
3991
+ * several requests. NOTE: we flatten nested arrays - results of each separate request done for the specific provider)
3992
+ * @throws Error if requests to all providers are failed
3993
+ */
3994
+ _proto.callExternalAPI = function callExternalAPI(parametersValues, timeoutMS, cancelToken, attemptsCount, doNotFailForNowData) {
3995
+ if (parametersValues === void 0) {
3996
+ parametersValues = [];
3997
+ }
3998
+ if (timeoutMS === void 0) {
3999
+ timeoutMS = 3500;
4000
+ }
4001
+ if (cancelToken === void 0) {
4002
+ cancelToken = null;
4003
+ }
4004
+ if (attemptsCount === void 0) {
4005
+ attemptsCount = 1;
4006
+ }
4007
+ if (doNotFailForNowData === void 0) {
4008
+ doNotFailForNowData = false;
4009
+ }
4010
+ try {
4011
+ var _this = this;
4012
+ var result;
4013
+ var calculationUuid = concurrentCalculationsMetadataHolder.startCalculation(_this.bio);
4014
+ return Promise.resolve(_finallyRethrows$1(function () {
4015
+ return _catch$4(function () {
4016
+ function _temp5() {
4017
+ var _result2, _result3;
4018
+ if (((_result2 = result) == null ? void 0 : _result2.data) == null) {
4019
+ // TODO: [feature, moderate] looks like we should not fail for null data as it is strange - the provider will fail when processing data internally
4020
+ var error = new Error("Failed to retrieve data. It means all attempts have been failed. DEV: add more attempts to this data retrieval");
4021
+ if (!doNotFailForNowData) {
4022
+ throw error;
4023
+ } else {
4024
+ _this._logger(error, _this.bio + ".callExternalAPI");
4025
+ }
4026
+ }
4027
+ return (_result3 = result) == null ? void 0 : _result3.data;
4028
+ }
4029
+ var i = 0;
4030
+ var _temp4 = _for(function () {
4031
+ var _result4, _result5;
4032
+ return (i < attemptsCount || !!((_result4 = result) != null && _result4.shouldBeForceRetried)) && ((_result5 = result) == null ? void 0 : _result5.data) == null;
4033
+ }, function () {
4034
+ return ++i;
4035
+ }, function () {
4036
+ /**
4037
+ * We use rpsFactor to improve re-attempting to call the providers if the last attempt resulted with
4038
+ * the fail due to abused RPSes of some (most part of) providers.
4039
+ * The _performCallAttempt in such a case will return increased rpsFactor inside the result object.
4040
+ */
4041
+ var rpsFactor = result ? result.rpsFactor : RobustExternalAPICallerService.defaultRPSFactor;
4042
+ result = null;
4043
+ var _temp3 = _catch$4(function () {
4044
+ function _temp2() {
4045
+ var _result$errors;
4046
+ if ((_result$errors = result.errors) != null && _result$errors.length) {
4047
+ var errors = result.errors;
4048
+ _this._logger(new Error("Failed at attempt " + i + ". " + errors.length + " errors. Messages: " + safeStringify(errors.map(function (error) {
4049
+ return error.message;
4050
+ })) + ": " + safeStringify(errors) + "."), _this.bio + ".callExternalAPI", "", true);
4051
+ }
4052
+ }
4053
+ var _temp = function (_result6) {
4054
+ if (i === 0 && !((_result6 = result) != null && _result6.shouldBeForceRetried)) {
4055
+ return Promise.resolve(_this._performCallAttempt(parametersValues, timeoutMS, cancelToken, rpsFactor, doNotFailForNowData)).then(function (_this$_performCallAtt) {
4056
+ result = _this$_performCallAtt;
4057
+ });
4058
+ } else {
4059
+ var maxRps = Math.max.apply(Math, _this.providers.map(function (provider) {
4060
+ var _provider$getRps;
4061
+ return (_provider$getRps = provider.getRps()) != null ? _provider$getRps : 0;
4062
+ }));
4063
+ var waitingTimeMs = maxRps ? 1000 / (maxRps / rpsFactor) : 0;
4064
+ return Promise.resolve(new Promise(function (resolve, reject) {
4065
+ setTimeout(function () {
4066
+ try {
4067
+ var _temp6 = _catch$4(function () {
4068
+ return Promise.resolve(_this._performCallAttempt(parametersValues, timeoutMS, cancelToken, rpsFactor, doNotFailForNowData)).then(function (_this$_performCallAtt2) {
4069
+ resolve(_this$_performCallAtt2);
4070
+ });
4071
+ }, function (e) {
4072
+ reject(e);
4073
+ });
4074
+ return Promise.resolve(_temp6 && _temp6.then ? _temp6.then(function () {}) : void 0);
4075
+ } catch (e) {
4076
+ return Promise.reject(e);
4077
+ }
4078
+ }, waitingTimeMs);
4079
+ })).then(function (_Promise) {
4080
+ result = _Promise;
4081
+ });
4082
+ }
4083
+ }();
4084
+ return _temp && _temp.then ? _temp.then(_temp2) : _temp2(_temp);
4085
+ }, function (e) {
4086
+ _this._logger(e, _this.bio + ".callExternalAPI", "Failed to perform external providers calling");
4087
+ });
4088
+ if (_temp3 && _temp3.then) return _temp3.then(function () {});
4089
+ });
4090
+ return _temp4 && _temp4.then ? _temp4.then(_temp5) : _temp5(_temp4);
4091
+ }, function (e) {
4092
+ improveAndRethrow(e, _this.bio + ".callExternalAPI");
4093
+ });
4094
+ }, function (_wasThrown, _result) {
4095
+ concurrentCalculationsMetadataHolder.endCalculation(_this.bio, calculationUuid);
4096
+ if (_wasThrown) throw _result;
4097
+ return _result;
4098
+ }));
4099
+ } catch (e) {
4100
+ return Promise.reject(e);
4101
+ }
4102
+ };
4103
+ _proto._performCallAttempt = function _performCallAttempt(parametersValues, timeoutMS, cancelToken, rpsFactor, doNotFailForNowData) {
4104
+ try {
4105
+ var _temp15 = function _temp15() {
4106
+ var _data;
4107
+ // If we are declining more than 50% of providers (by exceeding RPS) then we note that it better to retry the whole process of providers requesting
4108
+ var shouldBeForceRetried = data == null && countOfRequestsDeclinedByRps > Math.floor(providers.length * 0.5);
4109
+ var rpsMultiplier = shouldBeForceRetried ? RobustExternalAPICallerService.rpsMultiplier : 1;
4110
+ return {
4111
+ data: (_data = data) != null ? _data : null,
4112
+ shouldBeForceRetried: shouldBeForceRetried,
4113
+ rpsFactor: rpsFactor * rpsMultiplier,
4114
+ errors: errors
4115
+ };
4116
+ };
4117
+ var _this2 = this;
4118
+ var providers = _this2._reorderProvidersByNiceFactor();
4119
+ var data = undefined,
4120
+ providerIndex = 0,
4121
+ countOfRequestsDeclinedByRps = 0,
4122
+ errors = [];
4123
+ var _temp14 = _for(function () {
4124
+ return !data && providerIndex < providers.length;
4125
+ }, void 0, function () {
4126
+ var provider = providers[providerIndex];
4127
+ if (provider.isRpsExceeded()) {
4128
+ /**
4129
+ * Current provider's RPS is exceeded, so we try next provider. Also, we count such cases to make
4130
+ * a decision about the force-retry need.
4131
+ */
4132
+ ++providerIndex;
4133
+ ++countOfRequestsDeclinedByRps;
4134
+ return;
4135
+ }
4136
+ var _temp13 = _finallyRethrows$1(function () {
4137
+ return _catch$4(function () {
4138
+ var _provider$specificHea;
4139
+ function _temp12() {
4140
+ if (iterationsData.length) {
4141
+ if (httpMethods.length > 1) {
4142
+ data = provider.incorporateIterationsData(iterationsData);
4143
+ } else {
4144
+ data = iterationsData[0];
4145
+ }
4146
+ } else if (!doNotFailForNowData) {
4147
+ RobustExternalAPICallerService.statsCollector.externalServiceFailed(provider.getApiGroupId(), "Response data was null for some reason");
4148
+ punishProvider(provider);
4149
+ }
4150
+ }
4151
+ var axiosConfig = _extends({}, cancelToken ? {
4152
+ cancelToken: cancelToken
4153
+ } : {}, {
4154
+ timeout: provider.timeout || timeoutMS,
4155
+ headers: (_provider$specificHea = provider.specificHeaders) != null ? _provider$specificHea : {}
4156
+ });
4157
+ var httpMethods = Array.isArray(provider.httpMethod) ? provider.httpMethod : [provider.httpMethod];
4158
+ var iterationsData = [];
4159
+ var _temp11 = _forTo$1(httpMethods, function (subRequestIndex) {
4160
+ function _temp10() {
4161
+ var responsesDataForPages = responsesForPages.map(function (response) {
4162
+ return provider.getDataByResponse(response, parametersValues, subRequestIndex, iterationsData);
4163
+ });
4164
+ var allData = responsesDataForPages;
4165
+ if (Array.isArray(responsesDataForPages[0])) {
4166
+ allData = responsesDataForPages.flat();
4167
+ } else if (responsesDataForPages.length === 1) {
4168
+ allData = responsesDataForPages[0];
4169
+ }
4170
+ iterationsData.push(allData);
4171
+ }
4172
+ var query = provider.composeQueryString(parametersValues, subRequestIndex);
4173
+ var endpoint = "" + provider.endpoint + query;
4174
+ var axiosParams = [endpoint, axiosConfig];
4175
+ if (["post", "put", "patch"].find(function (method) {
4176
+ return method === httpMethods[subRequestIndex];
4177
+ })) {
4178
+ var _provider$composeBody;
4179
+ var body = (_provider$composeBody = provider.composeBody(parametersValues, subRequestIndex)) != null ? _provider$composeBody : null;
4180
+ axiosParams.splice(1, 0, body);
4181
+ }
4182
+ var pageNumber = 0;
4183
+ var responsesForPages = [];
4184
+ var hasNextPage = provider.doesSupportPagination();
4185
+ var _temp9 = _do(function () {
4186
+ function _temp8() {
4187
+ if (hasNextPage) {
4188
+ hasNextPage = !provider.checkWhetherResponseIsForLastPage(responsesForPages[pageNumber - 1], responsesForPages[pageNumber], pageNumber, subRequestIndex);
4189
+ }
4190
+ pageNumber++;
4191
+ }
4192
+ var _temp7 = function () {
4193
+ if (subRequestIndex === 0 && pageNumber === 0) {
4194
+ provider.actualizeLastCalledTimestamp();
4195
+ return Promise.resolve(AxiosAdapter.call.apply(AxiosAdapter, [httpMethods[subRequestIndex]].concat(axiosParams))).then(function (_AxiosAdapter$call) {
4196
+ responsesForPages[pageNumber] = _AxiosAdapter$call;
4197
+ RobustExternalAPICallerService.statsCollector.externalServiceCalledWithoutError(provider.getApiGroupId());
4198
+ });
4199
+ } else {
4200
+ if (pageNumber > 0) {
4201
+ var actualizedParams = provider.changeQueryParametersForPageNumber(parametersValues, responsesForPages[pageNumber - 1], pageNumber, subRequestIndex);
4202
+ var _query = provider.composeQueryString(actualizedParams, subRequestIndex);
4203
+ axiosParams[0] = "" + provider.endpoint + _query;
4204
+ }
4205
+ /**
4206
+ * For second and more request we postpone each request to not exceed RPS
4207
+ * of current provider. We use rpsFactor to dynamically increase the rps to avoid
4208
+ * too frequent calls if we continue failing to retrieve the data due to RPS exceeding.
4209
+ * TODO: [dev] test RPS factor logic (units or integration)
4210
+ */
4211
+
4212
+ var waitingTimeMS = provider.getRps() ? 1000 / (provider.getRps() / rpsFactor) : 0;
4213
+ var postponeUntilRpsExceeded = function postponeUntilRpsExceeded(recursionLevel) {
4214
+ if (recursionLevel === void 0) {
4215
+ recursionLevel = 0;
4216
+ }
4217
+ try {
4218
+ return Promise.resolve(postponeExecution(function () {
4219
+ try {
4220
+ var _temp17 = function _temp17(_result8) {
4221
+ if (_exit) return _result8;
4222
+ provider.actualizeLastCalledTimestamp();
4223
+ return Promise.resolve(AxiosAdapter.call.apply(AxiosAdapter, [httpMethods[subRequestIndex]].concat(axiosParams)));
4224
+ };
4225
+ var _exit;
4226
+ var maxCountOfPostponingAttempts = 2;
4227
+ var _temp16 = function () {
4228
+ if (provider.isRpsExceeded() && recursionLevel < maxCountOfPostponingAttempts) {
4229
+ return Promise.resolve(postponeUntilRpsExceeded(recursionLevel + 1)).then(function (_await$postponeUntilR) {
4230
+ _exit = 1;
4231
+ return _await$postponeUntilR;
4232
+ });
4233
+ }
4234
+ }();
4235
+ return Promise.resolve(_temp16 && _temp16.then ? _temp16.then(_temp17) : _temp17(_temp16));
4236
+ } catch (e) {
4237
+ return Promise.reject(e);
4238
+ }
4239
+ }, waitingTimeMS));
4240
+ } catch (e) {
4241
+ return Promise.reject(e);
4242
+ }
4243
+ };
4244
+ return Promise.resolve(postponeUntilRpsExceeded()).then(function (_postponeUntilRpsExce) {
4245
+ responsesForPages[pageNumber] = _postponeUntilRpsExce;
4246
+ });
4247
+ }
4248
+ }();
4249
+ return _temp7 && _temp7.then ? _temp7.then(_temp8) : _temp8(_temp7);
4250
+ }, function () {
4251
+ return !!hasNextPage;
4252
+ });
4253
+ return _temp9 && _temp9.then ? _temp9.then(_temp10) : _temp10(_temp9);
4254
+ });
4255
+ return _temp11 && _temp11.then ? _temp11.then(_temp12) : _temp12(_temp11);
4256
+ }, function (e) {
4257
+ punishProvider(provider);
4258
+ RobustExternalAPICallerService.statsCollector.externalServiceFailed(provider.getApiGroupId(), e == null ? void 0 : e.message);
4259
+ errors.push(e);
4260
+ });
4261
+ }, function (_wasThrown2, _result7) {
4262
+ providerIndex++;
4263
+ if (_wasThrown2) throw _result7;
4264
+ return _result7;
4265
+ });
4266
+ if (_temp13 && _temp13.then) return _temp13.then(function () {});
4267
+ });
4268
+ return Promise.resolve(_temp14 && _temp14.then ? _temp14.then(_temp15) : _temp15(_temp14));
4269
+ } catch (e) {
4270
+ return Promise.reject(e);
4271
+ }
4272
+ };
4273
+ _proto._reorderProvidersByNiceFactor = function _reorderProvidersByNiceFactor() {
4274
+ var providersCopy = [].concat(this.providers);
4275
+ return providersCopy.sort(function (p1, p2) {
4276
+ return p2.niceFactor - p1.niceFactor;
4277
+ });
4278
+ };
4279
+ return RobustExternalAPICallerService;
4280
+ }();
4281
+ RobustExternalAPICallerService.statsCollector = new ExternalServicesStatsCollector();
4282
+ RobustExternalAPICallerService.defaultRPSFactor = 1;
4283
+ RobustExternalAPICallerService.rpsMultiplier = 1.05;
4284
+ function punishProvider(provider) {
4285
+ provider.niceFactor = provider.niceFactor - 1;
4286
+ }
4287
+
4288
+ /**
4289
+ * Extended edit of RobustExternalApiCallerService supporting cache and management of concurrent requests
4290
+ * to the same resource.
4291
+ * TODO: [tests, critical] Massively used logic
4292
+ */
4293
+
4294
+ function _catch$3(body, recover) {
4295
+ try {
4296
+ var result = body();
4297
+ } catch (e) {
4298
+ return recover(e);
4299
+ }
4300
+ if (result && result.then) {
4301
+ return result.then(void 0, recover);
4302
+ }
4303
+ return result;
4304
+ }
4305
+ function _finallyRethrows(body, finalizer) {
4306
+ try {
4307
+ var result = body();
4308
+ } catch (e) {
4309
+ return finalizer(true, e);
4310
+ }
4311
+ if (result && result.then) {
4312
+ return result.then(finalizer.bind(null, false), finalizer.bind(null, true));
4313
+ }
4314
+ return finalizer(false, result);
4315
+ }
4316
+ var CachedRobustExternalApiCallerService = /*#__PURE__*/function () {
4317
+ /**
4318
+ * @param bio {string} unique service identifier
4319
+ * @param cache {Cache} cache instance
4320
+ * @param providersData {ExternalApiProvider[]} array of providers
4321
+ * @param [cacheTtlMs=10000] {number} time to live for cache ms
4322
+ * @param [maxCallAttemptsToWaitForAlreadyRunningRequest=50] {number} see details in CacheAndConcurrentRequestsResolver
4323
+ * @param [timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished=3000] {number} see details in CacheAndConcurrentRequestsResolver
4324
+ * @param [removeExpiredCacheAutomatically=true] {boolean} whether to remove cached data automatically when ttl exceeds
4325
+ * @param [mergeCachedAndNewlyRetrievedData=null] {function} function accepting cached data, newly retrieved data and id field name for list items
4326
+ * and merging them. use if needed
4327
+ */
4328
+ function CachedRobustExternalApiCallerService(bio, cache, providersData, cacheTtlMs, removeExpiredCacheAutomatically, mergeCachedAndNewlyRetrievedData, maxCallAttemptsToWaitForAlreadyRunningRequest, timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished) {
4329
+ if (cacheTtlMs === void 0) {
4330
+ cacheTtlMs = 10000;
4331
+ }
4332
+ if (removeExpiredCacheAutomatically === void 0) {
4333
+ removeExpiredCacheAutomatically = true;
4334
+ }
4335
+ if (mergeCachedAndNewlyRetrievedData === void 0) {
4336
+ mergeCachedAndNewlyRetrievedData = null;
4337
+ }
4338
+ if (maxCallAttemptsToWaitForAlreadyRunningRequest === void 0) {
4339
+ maxCallAttemptsToWaitForAlreadyRunningRequest = 100;
4340
+ }
4341
+ if (timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished === void 0) {
4342
+ timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished = 1000;
4343
+ }
4344
+ this._provider = new RobustExternalAPICallerService("cached_" + bio, providersData, Logger.logError);
4345
+ this._cacheTtlMs = cacheTtlMs;
4346
+ this._cahceAndRequestsResolver = new CacheAndConcurrentRequestsResolver(bio, cache, cacheTtlMs, removeExpiredCacheAutomatically, maxCallAttemptsToWaitForAlreadyRunningRequest, timeoutBetweenAttemptsToCheckWhetherAlreadyRunningRequestFinished);
4347
+ this._cahceIds = [];
4348
+ this._mergeCachedAndNewlyRetrievedData = mergeCachedAndNewlyRetrievedData;
4349
+ }
4350
+
4351
+ /**
4352
+ * Calls the external API or returns data from cache. Just waits if the same data already requested.
4353
+ *
4354
+ * @param parametersValues {array} array of values of the parameters for URL query string [and/or body]
4355
+ * @param timeoutMS {number} http timeout to wait for response. If provider has its specific timeout value then it is used
4356
+ * @param [cancelToken] {object|undefined} axios token to force-cancel requests from high-level code
4357
+ * @param [attemptsCount] {number|undefined} number of attempts to be performed
4358
+ * @param [customHashFunctionForParams] {function|undefined} function without params calculating the hash to be
4359
+ * added to bio of the service to compose a unique parameters-specific cache id
4360
+ * @param [doNotFailForNowData] {boolean|undefined} pass true if you do not want us to throw an error if we retrieved null data from all the providers
4361
+ * @return {Promise<any>} resolving to retrieved data (or array of results if specific provider requires
4362
+ * several requests. NOTE: we flatten nested arrays - results of each separate request done for the specific provider)
4363
+ * @throws Error if requests to all providers are failed
4364
+ */
4365
+ var _proto = CachedRobustExternalApiCallerService.prototype;
4366
+ _proto.callExternalAPICached = function callExternalAPICached(parametersValues, timeoutMS, cancelToken, attemptsCount, customHashFunctionForParams, doNotFailForNowData) {
4367
+ if (parametersValues === void 0) {
4368
+ parametersValues = [];
4369
+ }
4370
+ if (timeoutMS === void 0) {
4371
+ timeoutMS = 3500;
4372
+ }
4373
+ if (cancelToken === void 0) {
4374
+ cancelToken = null;
4375
+ }
4376
+ if (attemptsCount === void 0) {
4377
+ attemptsCount = 1;
4378
+ }
4379
+ if (customHashFunctionForParams === void 0) {
4380
+ customHashFunctionForParams = null;
4381
+ }
4382
+ if (doNotFailForNowData === void 0) {
4383
+ doNotFailForNowData = false;
4384
+ }
4385
+ try {
4386
+ var _this = this;
4387
+ var loggerSource = _this._provider.bio + ".callExternalAPICached";
4388
+ var cacheId;
4389
+ var result;
4390
+ return Promise.resolve(_finallyRethrows(function () {
4391
+ return _catch$3(function () {
4392
+ cacheId = _this._calculateCacheId(parametersValues, customHashFunctionForParams);
4393
+ return Promise.resolve(_this._cahceAndRequestsResolver.getCachedOrWaitForCachedOrAcquireLock(cacheId)).then(function (_this$_cahceAndReques) {
4394
+ var _result2, _result4;
4395
+ result = _this$_cahceAndReques;
4396
+ return (_result2 = result) != null && _result2.canStartDataRetrieval ? Promise.resolve(_this._provider.callExternalAPI(parametersValues, timeoutMS, cancelToken, attemptsCount, doNotFailForNowData)).then(function (data) {
4397
+ var canPerformMerge = typeof _this._mergeCachedAndNewlyRetrievedData === "function";
4398
+ if (canPerformMerge) {
4399
+ var mostRecentCached = _this._cahceAndRequestsResolver.getCached(cacheId);
4400
+ data = _this._mergeCachedAndNewlyRetrievedData(mostRecentCached, data, parametersValues);
4401
+ }
4402
+ if (data != null) {
4403
+ var _result3;
4404
+ _this._cahceAndRequestsResolver.saveCachedData(cacheId, (_result3 = result) == null ? void 0 : _result3.lockId, data, true, canPerformMerge);
4405
+ _this._cahceIds.indexOf(cacheId) < 0 && _this._cahceIds.push(cacheId);
4406
+ }
4407
+ return data;
4408
+ }) : (_result4 = result) == null ? void 0 : _result4.cachedData;
4409
+ });
4410
+ }, function (e) {
4411
+ improveAndRethrow(e, loggerSource);
4412
+ });
4413
+ }, function (_wasThrown, _result) {
4414
+ var _result5;
4415
+ _this._cahceAndRequestsResolver.releaseLock(cacheId, (_result5 = result) == null ? void 0 : _result5.lockId);
4416
+ if (_wasThrown) throw _result;
4417
+ return _result;
4418
+ }));
4419
+ } catch (e) {
4420
+ return Promise.reject(e);
4421
+ }
4422
+ };
4423
+ _proto.invalidateCaches = function invalidateCaches() {
4424
+ var _this2 = this;
4425
+ this._cahceIds.forEach(function (key) {
4426
+ return _this2._cahceAndRequestsResolver.invalidate(key);
4427
+ });
4428
+ };
4429
+ _proto.actualizeCachedData = function actualizeCachedData(params, synchronousCurrentCacheProcessor, customHashFunctionForParams, sessionDependent, actualizedAtTimestamp) {
4430
+ if (customHashFunctionForParams === void 0) {
4431
+ customHashFunctionForParams = null;
4432
+ }
4433
+ if (sessionDependent === void 0) {
4434
+ sessionDependent = true;
4435
+ }
4436
+ var cacheId = this._calculateCacheId(params, customHashFunctionForParams);
4437
+ this._cahceAndRequestsResolver.actualizeCachedData(cacheId, synchronousCurrentCacheProcessor, sessionDependent);
4438
+ };
4439
+ _proto.markCacheAsExpiredButDontRemove = function markCacheAsExpiredButDontRemove(parametersValues, customHashFunctionForParams) {
4440
+ try {
4441
+ this._cahceAndRequestsResolver.markAsExpiredButDontRemove(this._calculateCacheId(parametersValues, customHashFunctionForParams));
4442
+ } catch (e) {
4443
+ improveAndRethrow(e, "markCacheAsExpiredButDontRemove");
4444
+ }
4445
+ };
4446
+ _proto._calculateCacheId = function _calculateCacheId(parametersValues, customHashFunctionForParams) {
4447
+ if (customHashFunctionForParams === void 0) {
4448
+ customHashFunctionForParams = null;
4449
+ }
4450
+ try {
4451
+ var hash = typeof customHashFunctionForParams === "function" ? customHashFunctionForParams(parametersValues) : !parametersValues ? "" : new Hashes__default["default"].SHA512().hex(safeStringify(parametersValues));
4452
+ return this._provider.bio + "-" + hash;
4453
+ } catch (e) {
4454
+ improveAndRethrow(e, this._provider.bio + "_calculateCacheId");
4455
+ }
4456
+ };
4457
+ return CachedRobustExternalApiCallerService;
4458
+ }();
4459
+
4460
+ /**
4461
+ * Utils class needed to perform cancelling of axios request inside some process.
4462
+ * Provides cancel state and axios token for HTTP requests
4463
+ */
4464
+ var CancelProcessing = /*#__PURE__*/function () {
4465
+ function CancelProcessing() {
4466
+ this._cancelToken = axios__default["default"].CancelToken.source();
4467
+ this._isCanceled = false;
4468
+ }
4469
+ var _proto = CancelProcessing.prototype;
4470
+ _proto.cancel = function cancel() {
4471
+ this._isCanceled = true;
4472
+ this._cancelToken.cancel();
4473
+ };
4474
+ _proto.isCanceled = function isCanceled() {
4475
+ return this._isCanceled;
4476
+ };
4477
+ _proto.getToken = function getToken() {
4478
+ return this._cancelToken.token;
4479
+ };
4480
+ CancelProcessing.instance = function instance() {
4481
+ return new CancelProcessing();
4482
+ };
4483
+ return CancelProcessing;
4484
+ }();
4485
+
4486
+ var ExternalApiProvider = /*#__PURE__*/function () {
4487
+ /**
4488
+ * Creates an instance of external api provider.
4489
+ *
4490
+ * If you need sub-request then use 'subRequestIndex' to check current request index in functions below.
4491
+ * Also use array for 'httpMethod'.
4492
+ *
4493
+ * If the endpoint of dedicated provider has pagination then you should customize the behavior using
4494
+ * "changeQueryParametersForPageNumber", "checkWhetherResponseIsForLastPage".
4495
+ *
4496
+ * We perform RPS counting all over the App to avoid blocking our clients due to abuses of the providers.
4497
+ *
4498
+ * @param endpoint {string} URL to the provider's endpoint. Note: you can customize it using composeQueryString
4499
+ * @param [httpMethod] {string|string[]} one of "get", "post", "put", "patch", "delete" or an array of these values
4500
+ * for request having sub-requests
4501
+ * @param [timeout] {number} number of milliseconds to wait for the response
4502
+ * @param [apiGroup] {ApiGroup} singleton object containing parameters of API group. Helpful when you use the same
4503
+ * api for different providers to avoid hardcoding RPS inside each provider what can cause mistakes
4504
+ * @param [specificHeaders] {Object} contains specific keys (headers) and values (their content) if needed for this provider
4505
+ * @param [maxPageLength] {number} optional number of items per page if the request supports pagination
4506
+ */
4507
+ function ExternalApiProvider(endpoint, httpMethod, timeout, apiGroup, specificHeaders, maxPageLength) {
4508
+ var _maxPageLength, _specificHeaders;
4509
+ if (specificHeaders === void 0) {
4510
+ specificHeaders = {};
4511
+ }
4512
+ if (maxPageLength === void 0) {
4513
+ maxPageLength = Number.MAX_SAFE_INTEGER;
4514
+ }
4515
+ this.endpoint = endpoint;
4516
+ this.httpMethod = httpMethod != null ? httpMethod : "get";
4517
+ // TODO: [refactoring, critical] We have two timeouts for robust data retrieval - here and inside the service method call, need to remain the only
4518
+ this.timeout = timeout != null ? timeout : 10000;
4519
+ // TODO: [refactoring, critical] We need single place for all RPSes as we use them as hardcoded constants now inside different services
4520
+ this.apiGroup = apiGroup;
4521
+ this.maxPageLength = (_maxPageLength = maxPageLength) != null ? _maxPageLength : Number.MAX_SAFE_INTEGER;
4522
+ this.niceFactor = 1;
4523
+ this.specificHeaders = (_specificHeaders = specificHeaders) != null ? _specificHeaders : {};
4524
+ }
4525
+ var _proto = ExternalApiProvider.prototype;
4526
+ _proto.getRps = function getRps() {
4527
+ var _this$apiGroup$rps;
4528
+ return (_this$apiGroup$rps = this.apiGroup.rps) != null ? _this$apiGroup$rps : 2;
4529
+ };
4530
+ _proto.isRpsExceeded = function isRpsExceeded() {
4531
+ return this.apiGroup.isRpsExceeded();
4532
+ };
4533
+ _proto.actualizeLastCalledTimestamp = function actualizeLastCalledTimestamp() {
4534
+ this.apiGroup.actualizeLastCalledTimestamp();
4535
+ };
4536
+ _proto.getApiGroupId = function getApiGroupId() {
4537
+ return this.apiGroup.id;
4538
+ }
4539
+
4540
+ /**
4541
+ * Some endpoint can require several sub requests. Example is one request to get confirmed transactions
4542
+ * and another request for unconfirmed transactions. You should override this method to return true for such requests.
4543
+ *
4544
+ * @return {boolean} true if this provider requires several requests to retrieve the data
4545
+ */;
4546
+ _proto.doesRequireSubRequests = function doesRequireSubRequests() {
4547
+ return false;
4548
+ }
4549
+
4550
+ /**
4551
+ * Some endpoint support pagination. Override this method if so and implement corresponding methods.
4552
+ *
4553
+ * @return {boolean} true if this provider requires several requests to retrieve the data
4554
+ */;
4555
+ _proto.doesSupportPagination = function doesSupportPagination() {
4556
+ return false;
4557
+ }
4558
+
4559
+ /**
4560
+ * Composes a query string to be added to the endpoint of this provider.
4561
+ *
4562
+ * @param params {any[]} params array passed to the RobustExternalAPICallerService
4563
+ * @param [subRequestIndex] {number} optional number of the sub-request the call is performed for
4564
+ * @returns {string} query string to be concatenated with endpoint
4565
+ */;
4566
+ _proto.composeQueryString = function composeQueryString(params, subRequestIndex) {
4567
+ return "";
4568
+ }
4569
+
4570
+ /**
4571
+ * Composes a body to be added to the request
4572
+ *
4573
+ * @param params {any[]} params array passed to the RobustExternalAPICallerService
4574
+ * @param [subRequestIndex] {number} optional number of the sub-request the call is performed for
4575
+ * @returns {string}
4576
+ */;
4577
+ _proto.composeBody = function composeBody(params, subRequestIndex) {
4578
+ return "";
4579
+ }
4580
+
4581
+ /**
4582
+ * Extracts data from the response and returns it
4583
+ *
4584
+ * @param response {Object} HTTP response returned by provider
4585
+ * @param [params] {any[]} params array passed to the RobustExternalAPICallerService
4586
+ * @param [subRequestIndex] {number} optional number of the sub-request the call is performed for
4587
+ * @param iterationsData {any[]} array of data retrieved from previous sub-requests
4588
+ * @returns {any}
4589
+ */;
4590
+ _proto.getDataByResponse = function getDataByResponse(response, params, subRequestIndex, iterationsData) {
4591
+ return [];
4592
+ }
4593
+
4594
+ /**
4595
+ * Function changing the query string according to page number and previous response
4596
+ * Only for endpoints supporting pagination
4597
+ *
4598
+ * @param params {any[]} params array passed to the RobustExternalAPICallerService
4599
+ * @param previousResponse {Object} HTTP response returned by provider for previous call (previous page)
4600
+ * @param pageNumber {number} new page number. We count from 0. You need to manually increment with 1 if your
4601
+ * provider counts pages starting with 1
4602
+ * @param [subRequestIndex] {number} optional number of the sub-request the call is performed for
4603
+ * @returns {any[]}
4604
+ */;
4605
+ _proto.changeQueryParametersForPageNumber = function changeQueryParametersForPageNumber(params, previousResponse, pageNumber, subRequestIndex) {
4606
+ return params;
4607
+ }
4608
+
4609
+ /**
4610
+ * Function checking whether the response is for the last page to stop requesting for a next page.
4611
+ * Only for endpoints supporting pagination.
4612
+ *
4613
+ * @param previousResponse {Object} HTTP response returned by provider for previous call (previous page)
4614
+ * @param currentResponse {Object} HTTP response returned by provider for current call (current page, next after the previous)
4615
+ * @param currentPageNumber {number} current page number (for current response)
4616
+ * @param [subRequestIndex] {number} optional number of the sub-request the call is performed for
4617
+ * @returns {boolean}
4618
+ */;
4619
+ _proto.checkWhetherResponseIsForLastPage = function checkWhetherResponseIsForLastPage(previousResponse, currentResponse, currentPageNumber, subRequestIndex) {
4620
+ return true;
4621
+ }
4622
+
4623
+ /**
4624
+ * Resets the nice factor to default value
4625
+ */;
4626
+ _proto.resetNiceFactor = function resetNiceFactor() {
4627
+ this.niceFactor = 1;
4628
+ }
4629
+
4630
+ /**
4631
+ * Internal method used for requests requiring sub-requests.
4632
+ *
4633
+ * @param iterationsData {any[]} iterations data retrieved from getDataByResponse called per sub-request.
4634
+ * @return {any} by default flatten the passed iterations data array. Should be redefined if you need another logic.
4635
+ */;
4636
+ _proto.incorporateIterationsData = function incorporateIterationsData(iterationsData) {
4637
+ return iterationsData.flat();
4638
+ };
4639
+ return ExternalApiProvider;
4640
+ }();
4641
+
2617
4642
  var ExistingSwap =
2618
4643
  /**
2619
4644
  * @param swapId {string}
@@ -4588,26 +6613,39 @@ PublicSwapService._fiatDecimalsCount = FiatCurrenciesService.getCurrencyDecimalC
4588
6613
 
4589
6614
  exports.AmountUtils = AmountUtils;
4590
6615
  exports.AssetIcon = AssetIcon;
6616
+ exports.AxiosAdapter = AxiosAdapter;
4591
6617
  exports.BaseSwapCreationInfo = BaseSwapCreationInfo;
4592
6618
  exports.Blockchain = Blockchain;
4593
6619
  exports.Button = Button;
4594
6620
  exports.Cache = Cache;
6621
+ exports.CacheAndConcurrentRequestsResolver = CacheAndConcurrentRequestsResolver;
6622
+ exports.CachedRobustExternalApiCallerService = CachedRobustExternalApiCallerService;
6623
+ exports.CancelProcessing = CancelProcessing;
4595
6624
  exports.Coin = Coin;
4596
6625
  exports.EmailsApi = EmailsApi;
4597
6626
  exports.ExistingSwap = ExistingSwap;
4598
6627
  exports.ExistingSwapWithFiatData = ExistingSwapWithFiatData;
6628
+ exports.ExternalApiProvider = ExternalApiProvider;
4599
6629
  exports.FiatCurrenciesService = FiatCurrenciesService;
4600
6630
  exports.LoadingDots = LoadingDots;
4601
6631
  exports.Logger = Logger;
4602
6632
  exports.LogsStorage = LogsStorage;
4603
6633
  exports.Protocol = Protocol;
4604
6634
  exports.PublicSwapService = PublicSwapService;
6635
+ exports.RobustExternalAPICallerService = RobustExternalAPICallerService;
4605
6636
  exports.SupportChat = SupportChat;
4606
6637
  exports.SwapProvider = SwapProvider;
4607
6638
  exports.SwapUtils = SwapUtils;
4608
6639
  exports.SwapspaceSwapProvider = SwapspaceSwapProvider;
6640
+ exports.getQueryParameterSingleValue = getQueryParameterSingleValue;
6641
+ exports.getQueryParameterValues = getQueryParameterValues;
6642
+ exports.handleClickOutside = handleClickOutside;
4609
6643
  exports.improveAndRethrow = improveAndRethrow;
6644
+ exports.logErrorOrOutputToConsole = logErrorOrOutputToConsole;
6645
+ exports.postponeExecution = postponeExecution;
6646
+ exports.removeQueryParameterAndValues = removeQueryParameterAndValues;
4610
6647
  exports.safeStringify = safeStringify;
6648
+ exports.saveQueryParameterAndValues = saveQueryParameterAndValues;
4611
6649
  exports.useCallHandlingErrors = useCallHandlingErrors;
4612
6650
  exports.useReferredState = useReferredState;
4613
6651
  //# sourceMappingURL=index.cjs.map