Analyseer Exact Online API gebruik met `RateLimits` of `SystemPartitions`

De Exact Online API’s beperken het aantal requests per dag, per company en per app. Deze limieten worden geleidelijk verlaagd. Om storingen te voorkomen is het handig om inzicht te krijgen wat het huidige API-gebruik is.

Afhankelijk van de versie is hiervoor een van de volgende views beschikbaar:

  • RateLimits: uitsluitend voor beperkt aantal drivers zoals Exact Online en Freshdesk. Beschikbaar tot/met 20.2.128. In hogere versies is deze view vervallen.
  • SystemPartitions@DataDictionary: voor alle drivers toont deze view de geregistreerde limieten qua aantal requests. Beschikbaar vanaf 20.2.129.

SystemPartitions@DataDictionary

De volgende query:

select PROVIDER_NAME
,      PROVIDER_DATA_CONTAINER_ALIAS
,      CODE
,      CONSUMPTION_LAST_CALL
,      DAILY_LIMIT
,      DAILY_USED
,      DAILY_REMAINING
,      DAILY_RESET_DATE_UTC
,      MINUTELY_LIMIT
,      MINUTELY_REMAINING
,      MINUTELY_RESET_DATE_UTC
,      LAST_MEASUREMENT_UTC
,      FIRST_DAILY_REMAINING
,      FIRST_MINUTELY_REMAINING
,      FIRST_MEASUREMENT_UTC
,      UPDATE_COUNT
,      UPDATE_WITH_CHANGE_COUNT
,      PREVIOUS_DAILY_REMAINING
,      PREVIOUS_MINUTELY_REMAINING
,      PREVIOUS_MEASUREMENT_UTC
,      PREVIOUS_MINUTE_DAILY_REMAINING
,      PREVIOUS_MINUTE_DAILY_TIMESTAMP_UTC
,      PREVIOUS_HOUR_DAILY_REMAINING
,      PREVIOUS_HOUR_DAILY_TIMESTAMP_UTC
,      PREVIOUS_DAY_DAILY_REMAINING
,      PREVIOUS_DAY_DAILY_TIMESTAMP_UTC
from   SYSTEMPARTITIONS@DataDictionary

RateLimits

De view RateLimits toont de terugkoppeling vanuit Exact Online API-servers over het beschikbare en gebruikte/resterende aantal API-calls. Hierbij wordt onderscheid gemaakt tussen rate limits op dagniveau en op minuutniveau. Aangezien de inhoud vrijwel identiek is aan de nieuwe generieke view SystemPartitions@DataDictionary is deze niet verder hier uitgewerkt.

Bestaande programmatuur zal een kleine aanpassing behoeven. De volgende query verwijdert bijvoorbeeld geleidelijk overtollige contactpersonen die door herhaaldelijk importeren via XML van Accounts zijn ontstaan en stopt als er nog maar 10.000 API-calls over zijn:

--
-- Slowly remove all contacts.
--
-- Determine threshold as greatest of 0 and the value.
--
select 2 val
union
select (1000 - (trunc(sysdateutc) - to_date('20201015', 'YYYYMMDD')) * 10) val
order
by     val desc
limit  1

local define THRESHOLD_DUP_CTT "${outcome:0,0}"

create or replace table dupctt@inmemorystorage
as
select ctt.division
,      ctt.account
,      ctt.id
from   exactonlinerest..contactsincremental@eol ctt

create or replace table dupcttsum@inmemorystorage
as
select t.division
,      t.account
,      cnt
from   ( select ctt.division
         ,      ctt.account
         ,      count(*) cnt
         from   dupctt@inmemorystorage ctt
         group
         by     ctt.division
         ,      ctt.account
       ) t
where  t.cnt > ${THRESHOLD_DUP_CTT}
--
-- Has at least a duplicate.
--
and    t.cnt >= 2

--
-- Sysdateutc evaluates to a constant, so we need an extra check on number of deletes.
--
declare
  g_max_runtime_sec         pls_integer := 900;
  g_min_remaining_api_calls pls_integer := 10000;
  g_max_delete_cnt          pls_integer := 2500;
  --
  l_daily_last_remaining    pls_integer;
  l_start_time              date;
  l_delete_cnt              pls_integer;
begin
  set ignore-http-503-errors@eol true;
  l_start_time := sysdateutc;
  l_delete_cnt := 0;
  --
  for r in
  ( select dct.division
    ,      dct.account
    from   dupcttsum@inmemorystorage dct
    order
    by     dct.division
    ,      dct.account
  )
  loop
    select DailyLastRemaining
    into   l_daily_last_remaining
    from   ratelimits@eol
    where  division = r.division
    ;
    --
    -- At most one hour.
    --
    if l_delete_cnt < g_max_delete_cnt
       and l_daily_last_remaining > g_min_remaining_api_calls
       and (sysdateutc - l_start_time) < g_max_runtime_sec / 86400
    then
      delete exactonlinerest..contacts@eol
      where  division = r.division
      and    id
             in
             ( select /*+ low_cost */
                      id
               from   dupctt@inmemorystorage ctt
               where  account = r.account
             )
      ;
      l_delete_cnt := l_delete_cnt + 1;
    end if;
  end loop;
  --
  set ignore-http-503-errors@eol false;
end;

De query zal een foutmelding geven:

itgengpr015:
Unknown table ‘RATELIMITS’.
Possible valid alternatives: Units, Items, PriceLists, Assets, Statements.

Het volgende Invantive PSQL-statement kan vervangen worden:

select DailyLastRemaining
into   l_daily_last_remaining
from   ratelimits@eol
where  division = r.division

door:

select DAILY_REMAINING
into   l_daily_last_remaining
from   SYSTEMPARTITIONS@DataDictionary
where  CODE = r.division