2020-05-13 15:33:16 +03:00
|
|
|
module Hasura.RQL.DDL.ScheduledTrigger
|
|
|
|
( runCreateCronTrigger
|
|
|
|
, runDeleteCronTrigger
|
2020-12-08 17:22:31 +03:00
|
|
|
, dropCronTriggerInMetadata
|
2020-05-13 15:33:16 +03:00
|
|
|
, resolveCronTrigger
|
|
|
|
, runCreateScheduledEvent
|
|
|
|
) where
|
|
|
|
|
2020-10-27 16:53:49 +03:00
|
|
|
import Hasura.Backends.Postgres.Connection
|
2020-05-13 15:33:16 +03:00
|
|
|
import Hasura.EncJSON
|
2020-10-27 16:53:49 +03:00
|
|
|
import Hasura.Eventing.ScheduledTrigger
|
2020-05-13 15:33:16 +03:00
|
|
|
import Hasura.Prelude
|
2020-10-27 16:53:49 +03:00
|
|
|
import Hasura.RQL.DDL.EventTrigger (getHeaderInfosFromConf)
|
2020-05-13 15:33:16 +03:00
|
|
|
import Hasura.RQL.Types
|
|
|
|
|
2020-10-27 16:53:49 +03:00
|
|
|
import qualified Data.Environment as Env
|
|
|
|
import qualified Data.HashMap.Strict as Map
|
2020-12-08 17:22:31 +03:00
|
|
|
import qualified Data.HashMap.Strict.InsOrd as OMap
|
2020-10-27 16:53:49 +03:00
|
|
|
import qualified Data.Time.Clock as C
|
|
|
|
import qualified Database.PG.Query as Q
|
2020-05-13 15:33:16 +03:00
|
|
|
|
|
|
|
-- | runCreateCronTrigger will update a existing cron trigger when the 'replace'
|
|
|
|
-- value is set to @true@ and when replace is @false@ a new cron trigger will
|
|
|
|
-- be created
|
2020-12-08 17:22:31 +03:00
|
|
|
runCreateCronTrigger
|
|
|
|
:: (CacheRWM m, MonadTx m, MonadIO m, MetadataM m) => CreateCronTrigger -> m EncJSON
|
2020-05-13 15:33:16 +03:00
|
|
|
runCreateCronTrigger CreateCronTrigger {..} = do
|
2020-10-28 19:40:33 +03:00
|
|
|
let q = CronTriggerMetadata cctName
|
2020-05-13 15:33:16 +03:00
|
|
|
cctWebhook
|
|
|
|
cctCronSchedule
|
|
|
|
cctPayload
|
|
|
|
cctRetryConf
|
|
|
|
cctHeaders
|
|
|
|
cctIncludeInMetadata
|
2020-10-28 19:40:33 +03:00
|
|
|
cctComment
|
2020-05-13 15:33:16 +03:00
|
|
|
case cctReplace of
|
|
|
|
True -> updateCronTrigger q
|
|
|
|
False -> do
|
|
|
|
cronTriggersMap <- scCronTriggers <$> askSchemaCache
|
|
|
|
case Map.lookup (ctName q) cronTriggersMap of
|
|
|
|
Nothing -> pure ()
|
|
|
|
Just _ -> throw400 AlreadyExists $
|
|
|
|
"cron trigger with name: "
|
2020-10-28 19:40:33 +03:00
|
|
|
<> triggerNameToTxt (ctName q)
|
2020-05-13 15:33:16 +03:00
|
|
|
<> " already exists"
|
|
|
|
|
2020-12-08 17:22:31 +03:00
|
|
|
let metadataObj = MOCronTrigger cctName
|
|
|
|
metadata = CronTriggerMetadata cctName cctWebhook cctCronSchedule
|
|
|
|
cctPayload cctRetryConf cctHeaders cctIncludeInMetadata
|
|
|
|
cctComment
|
|
|
|
buildSchemaCacheFor metadataObj
|
|
|
|
$ MetadataModifier
|
|
|
|
$ metaCronTriggers %~ OMap.insert cctName metadata
|
|
|
|
currentTime <- liftIO C.getCurrentTime
|
|
|
|
let scheduleTimes = generateScheduleTimes currentTime 100 cctCronSchedule -- generate next 100 events
|
|
|
|
liftTx $ insertScheduledEventTx $ SESCron $ map (CronEventSeed cctName) scheduleTimes
|
2020-05-13 15:33:16 +03:00
|
|
|
return successMsg
|
|
|
|
|
|
|
|
resolveCronTrigger
|
2020-07-14 22:00:58 +03:00
|
|
|
:: (QErrM m)
|
|
|
|
=> Env.Environment
|
2020-12-08 17:22:31 +03:00
|
|
|
-> CronTriggerMetadata
|
2020-07-14 22:00:58 +03:00
|
|
|
-> m CronTriggerInfo
|
2020-12-08 17:22:31 +03:00
|
|
|
resolveCronTrigger env CronTriggerMetadata{..} = do
|
|
|
|
webhookInfo <- resolveWebhook env ctWebhook
|
|
|
|
headerInfo <- getHeaderInfosFromConf env ctHeaders
|
2020-05-13 15:33:16 +03:00
|
|
|
pure $
|
2020-12-08 17:22:31 +03:00
|
|
|
CronTriggerInfo ctName
|
|
|
|
ctSchedule
|
|
|
|
ctPayload
|
|
|
|
ctRetryConf
|
2020-05-13 15:33:16 +03:00
|
|
|
webhookInfo
|
|
|
|
headerInfo
|
2020-12-08 17:22:31 +03:00
|
|
|
ctComment
|
2020-05-13 15:33:16 +03:00
|
|
|
|
2020-12-08 17:22:31 +03:00
|
|
|
updateCronTrigger
|
|
|
|
:: ( CacheRWM m
|
|
|
|
, MonadTx m
|
|
|
|
, MonadIO m
|
|
|
|
, MetadataM m
|
|
|
|
)
|
|
|
|
=> CronTriggerMetadata -> m EncJSON
|
2020-05-13 15:33:16 +03:00
|
|
|
updateCronTrigger cronTriggerMetadata = do
|
2020-12-08 17:22:31 +03:00
|
|
|
let triggerName = ctName cronTriggerMetadata
|
|
|
|
checkExists triggerName
|
|
|
|
buildSchemaCacheFor (MOCronTrigger triggerName)
|
|
|
|
$ MetadataModifier
|
|
|
|
$ metaCronTriggers %~ OMap.insert triggerName cronTriggerMetadata
|
|
|
|
liftTx $ dropFutureCronEvents triggerName
|
2020-06-23 18:21:34 +03:00
|
|
|
currentTime <- liftIO C.getCurrentTime
|
2020-12-08 17:22:31 +03:00
|
|
|
let scheduleTimes = generateScheduleTimes currentTime 100 $ ctSchedule cronTriggerMetadata
|
|
|
|
liftTx $ insertScheduledEventTx $ SESCron $ map (CronEventSeed triggerName) scheduleTimes
|
|
|
|
pure successMsg
|
2020-05-13 15:33:16 +03:00
|
|
|
|
2020-12-08 17:22:31 +03:00
|
|
|
runDeleteCronTrigger
|
|
|
|
:: ( CacheRWM m
|
|
|
|
, MonadTx m
|
|
|
|
, MetadataM m
|
|
|
|
)
|
|
|
|
=> ScheduledTriggerName -> m EncJSON
|
2020-05-13 15:33:16 +03:00
|
|
|
runDeleteCronTrigger (ScheduledTriggerName stName) = do
|
|
|
|
checkExists stName
|
2020-12-08 17:22:31 +03:00
|
|
|
withNewInconsistentObjsCheck
|
|
|
|
$ buildSchemaCache
|
|
|
|
$ dropCronTriggerInMetadata stName
|
|
|
|
liftTx $ dropFutureCronEvents stName
|
2020-05-13 15:33:16 +03:00
|
|
|
return successMsg
|
|
|
|
|
2020-12-08 17:22:31 +03:00
|
|
|
dropFutureCronEvents :: TriggerName -> Q.TxE QErr ()
|
|
|
|
dropFutureCronEvents name =
|
2020-05-13 15:33:16 +03:00
|
|
|
Q.unitQE defaultTxErrorHandler
|
|
|
|
[Q.sql|
|
2020-12-08 17:22:31 +03:00
|
|
|
DELETE FROM hdb_catalog.hdb_cron_events
|
|
|
|
WHERE trigger_name = $1 AND scheduled_time > now() AND tries = 0
|
|
|
|
|] (Identity name) False
|
|
|
|
|
|
|
|
dropCronTriggerInMetadata :: TriggerName -> MetadataModifier
|
|
|
|
dropCronTriggerInMetadata name =
|
|
|
|
MetadataModifier $ metaCronTriggers %~ OMap.delete name
|
2020-05-13 15:33:16 +03:00
|
|
|
|
|
|
|
runCreateScheduledEvent :: (MonadTx m) => CreateScheduledEvent -> m EncJSON
|
|
|
|
runCreateScheduledEvent CreateScheduledEvent {..} = do
|
|
|
|
liftTx $ Q.unitQE defaultTxErrorHandler
|
|
|
|
[Q.sql|
|
|
|
|
INSERT INTO hdb_catalog.hdb_scheduled_events
|
|
|
|
(webhook_conf,scheduled_time,payload,retry_conf,header_conf,comment)
|
|
|
|
VALUES
|
|
|
|
($1, $2, $3, $4, $5, $6)
|
|
|
|
|] ( Q.AltJ cseWebhook
|
|
|
|
, cseScheduleAt
|
|
|
|
, Q.AltJ csePayload
|
|
|
|
, Q.AltJ cseRetryConf
|
|
|
|
, Q.AltJ cseHeaders
|
|
|
|
, cseComment)
|
|
|
|
False
|
|
|
|
pure successMsg
|
|
|
|
|
|
|
|
checkExists :: (CacheRM m, MonadError QErr m) => TriggerName -> m ()
|
|
|
|
checkExists name = do
|
|
|
|
cronTriggersMap <- scCronTriggers <$> askSchemaCache
|
|
|
|
void $ onNothing (Map.lookup name cronTriggersMap) $
|
|
|
|
throw400 NotExists $
|
2020-10-28 19:40:33 +03:00
|
|
|
"cron trigger with name: " <> triggerNameToTxt name <> " does not exist"
|