-
Notifications
You must be signed in to change notification settings - Fork 3
/
TaskManager_pollTask.sql
49 lines (48 loc) · 2.59 KB
/
TaskManager_pollTask.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* Her ligger all logikk for å fordele tasker på tvers av flere pollere,
* plukke tasker avhengig av om der klare for å kjøres (status + neste_kjoering_etter tid er passert), og
* besørge at tasker kjøres i rekkefølge de var ment (sekvensielt eller parallellt).
* <p>
* SELECT'en er basert på to ting som er verdt å forstå når man leser denne.
* <ul>
* <li>SELECT FOR UPDATE SKIP LOCKED: Benyttes til å spre tasker på tvers av flere pollere slik at de ikke går i
* beina på hverandre. Gir dermed mulighet for økt skalerbarhet og fleksible kjøring</li>
* <li>SQL WINDOW Functions: ANSI SQL standard for partisjonering av resultater. Brukes for å finne lavest
* nummerererte tasker i en gruppe (de som skal kjøre før de andre). Ligner GROUP BY men kan opererere på
* subresultater (så vesentlig kraftigere)</li>
* </ul>
*/
SELECT pt.*
FROM prosess_task pt
WHERE pt.id
IN (
-- Må beytte en IN clause istdf. JOIN, ellers kaster SKIP LOCKED exception (ORA-02014).
-- Gir oss ett ekstra nivå av subquery
SELECT tbl.ID
FROM
(
SELECT id
, task_type
-- SQL Window Function: finn første sekvens i task_gruppe. (dersom task_gruppe er NULL brukes task_type her som substitutt)
, FIRST_VALUE(task_sekvens) OVER (PARTITION BY coalesce(task_gruppe, task_type) ORDER BY length(task_sekvens), task_sekvens ASC NULLS FIRST, siste_kjoering_ts ASC NULLS FIRST, prioritet DESC) AS foerste_sekvens
, task_sekvens
, status
, feilede_forsoek
FROM prosess_task pt
WHERE
-- bruker dette istdf. (status NOT IN('FERDIG', 'KJOERT')). Innført for å bruke partisjoner med minst data, unngår skanning av alle partisjoner
status in ('FEILET', 'KLAR', 'VENTER_SVAR', 'SUSPENDERT', 'VETO')
) tbl
WHERE
-- filtrer vekk de som ikke har samme sekvensnr som første i gruppen, og som er KLAR
tbl.task_sekvens=tbl.foerste_sekvens
AND tbl.status IN ('KLAR')
)
-- fjerner de som har mindre enn maks antall feilde forsøk
-- håndterer at kjøring ikke skjer før angitt tidstempel
AND (pt.neste_kjoering_etter IS NULL OR pt.neste_kjoering_etter < :neste_kjoering)
AND status = 'KLAR' -- effektiviserer planen med bedre indeks
AND pt.id NOT IN (:skip_ids) -- sjekk mot skip ids i ytre loop ellers paavirkes rekkefølge
-- sorter etter prioritet og når de sist ble kjørt
ORDER BY prioritet DESC, siste_kjoering_ts ASC NULLS FIRST, ID ASC
FOR UPDATE SKIP LOCKED