2019-03-25 20:10:52 +03:00
|
|
|
module Hasura.RQL.DDL.EventTrigger
|
2018-12-13 10:26:15 +03:00
|
|
|
( CreateEventTriggerQuery
|
|
|
|
, runCreateEventTriggerQuery
|
|
|
|
, DeleteEventTriggerQuery
|
|
|
|
, runDeleteEventTriggerQuery
|
2019-05-13 12:41:07 +03:00
|
|
|
, RedeliverEventQuery
|
|
|
|
, runRedeliverEvent
|
|
|
|
, runInvokeEventTrigger
|
2018-12-13 10:26:15 +03:00
|
|
|
|
|
|
|
-- TODO: review
|
|
|
|
, delEventTriggerFromCatalog
|
|
|
|
, subTableP2
|
|
|
|
, subTableP2Setup
|
2019-05-13 12:41:07 +03:00
|
|
|
, mkAllTriggersQ
|
2019-03-01 16:59:24 +03:00
|
|
|
, getEventTriggerDef
|
|
|
|
, updateEventTriggerDef
|
2018-12-13 10:26:15 +03:00
|
|
|
) where
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
|
|
import Data.Aeson
|
2019-03-18 19:22:21 +03:00
|
|
|
import Hasura.EncJSON
|
2019-03-25 20:10:52 +03:00
|
|
|
import Hasura.Prelude
|
2018-11-23 16:02:46 +03:00
|
|
|
import Hasura.RQL.DDL.Headers
|
2018-10-09 09:39:20 +03:00
|
|
|
import Hasura.RQL.DML.Internal
|
2018-09-05 14:26:46 +03:00
|
|
|
import Hasura.RQL.Types
|
2018-09-29 08:42:47 +03:00
|
|
|
import Hasura.Server.Utils
|
2018-09-05 14:26:46 +03:00
|
|
|
import Hasura.SQL.Types
|
2018-10-09 09:39:20 +03:00
|
|
|
import System.Environment (lookupEnv)
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2018-10-09 09:39:20 +03:00
|
|
|
import qualified Hasura.SQL.DML as S
|
|
|
|
|
|
|
|
import qualified Data.FileEmbed as FE
|
|
|
|
import qualified Data.HashMap.Strict as HashMap
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import qualified Database.PG.Query as Q
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
|
|
|
|
|
|
data OpVar = OLD | NEW deriving (Show)
|
|
|
|
|
|
|
|
triggerTmplt :: Maybe GingerTmplt
|
|
|
|
triggerTmplt = case parseGingerTmplt $(FE.embedStringFile "src-rsr/trigger.sql.j2") of
|
|
|
|
Left _ -> Nothing
|
|
|
|
Right tmplt -> Just tmplt
|
|
|
|
|
2018-11-13 08:58:55 +03:00
|
|
|
pgIdenTrigger:: Ops -> TriggerName -> T.Text
|
|
|
|
pgIdenTrigger op trn = pgFmtIden (qualifyTriggerName op trn)
|
|
|
|
where
|
|
|
|
qualifyTriggerName op' trn' = "notify_hasura_" <> trn' <> "_" <> T.pack (show op')
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
getDropFuncSql :: Ops -> TriggerName -> T.Text
|
|
|
|
getDropFuncSql op trn = "DROP FUNCTION IF EXISTS"
|
2018-11-13 08:58:55 +03:00
|
|
|
<> " hdb_views." <> pgIdenTrigger op trn <> "()"
|
2018-09-05 14:26:46 +03:00
|
|
|
<> " CASCADE"
|
|
|
|
|
2018-10-09 09:39:20 +03:00
|
|
|
getTriggerSql
|
|
|
|
:: Ops
|
|
|
|
-> TriggerName
|
|
|
|
-> QualifiedTable
|
|
|
|
-> [PGColInfo]
|
2019-03-01 14:45:04 +03:00
|
|
|
-> Bool
|
2019-05-13 12:41:07 +03:00
|
|
|
-> SubscribeOpSpec
|
2018-10-09 09:39:20 +03:00
|
|
|
-> Maybe T.Text
|
2019-03-25 20:10:52 +03:00
|
|
|
getTriggerSql op trn qt allCols strfyNum spec =
|
2018-10-09 09:39:20 +03:00
|
|
|
let globalCtx = HashMap.fromList
|
2019-03-25 20:10:52 +03:00
|
|
|
[ (T.pack "NAME", trn)
|
2018-11-13 08:58:55 +03:00
|
|
|
, (T.pack "QUALIFIED_TRIGGER_NAME", pgIdenTrigger op trn)
|
2018-10-09 09:39:20 +03:00
|
|
|
, (T.pack "QUALIFIED_TABLE", toSQLTxt qt)
|
|
|
|
]
|
2019-05-13 12:41:07 +03:00
|
|
|
opCtx = createOpCtx op spec
|
2018-09-05 14:26:46 +03:00
|
|
|
context = HashMap.union globalCtx opCtx
|
|
|
|
in
|
2019-05-13 12:41:07 +03:00
|
|
|
renderGingerTmplt context <$> triggerTmplt
|
2018-09-05 14:26:46 +03:00
|
|
|
where
|
2018-10-25 10:22:51 +03:00
|
|
|
createOpCtx op1 (SubscribeOpSpec columns payload) =
|
2018-10-09 09:39:20 +03:00
|
|
|
HashMap.fromList
|
|
|
|
[ (T.pack "OPERATION", T.pack $ show op1)
|
2018-10-25 10:22:51 +03:00
|
|
|
, (T.pack "OLD_ROW", toSQLTxt $ renderRow OLD columns )
|
|
|
|
, (T.pack "NEW_ROW", toSQLTxt $ renderRow NEW columns )
|
|
|
|
, (T.pack "OLD_PAYLOAD_EXPRESSION", toSQLTxt $ renderOldDataExp op1 $ fromMaybePayload payload )
|
|
|
|
, (T.pack "NEW_PAYLOAD_EXPRESSION", toSQLTxt $ renderNewDataExp op1 $ fromMaybePayload payload )
|
2018-10-09 09:39:20 +03:00
|
|
|
]
|
|
|
|
renderOldDataExp op2 scs =
|
|
|
|
case op2 of
|
|
|
|
INSERT -> S.SEUnsafe "NULL"
|
|
|
|
UPDATE -> getRowExpression OLD scs
|
|
|
|
DELETE -> getRowExpression OLD scs
|
2019-05-13 12:41:07 +03:00
|
|
|
MANUAL -> S.SEUnsafe "NULL"
|
2018-10-09 09:39:20 +03:00
|
|
|
renderNewDataExp op2 scs =
|
|
|
|
case op2 of
|
|
|
|
INSERT -> getRowExpression NEW scs
|
|
|
|
UPDATE -> getRowExpression NEW scs
|
|
|
|
DELETE -> S.SEUnsafe "NULL"
|
2019-05-13 12:41:07 +03:00
|
|
|
MANUAL -> S.SEUnsafe "NULL"
|
2018-10-09 09:39:20 +03:00
|
|
|
getRowExpression opVar scs =
|
|
|
|
case scs of
|
|
|
|
SubCStar -> applyRowToJson $ S.SEUnsafe $ opToTxt opVar
|
|
|
|
SubCArray cols -> applyRowToJson $
|
|
|
|
S.mkRowExp $ map (toExtr . mkQId opVar) $
|
|
|
|
getColInfos cols allCols
|
|
|
|
|
|
|
|
applyRowToJson e = S.SEFnApp "row_to_json" [e] Nothing
|
2018-10-25 10:22:51 +03:00
|
|
|
applyRow e = S.SEFnApp "row" [e] Nothing
|
2018-10-09 09:39:20 +03:00
|
|
|
toExtr = flip S.Extractor Nothing
|
2019-03-01 14:45:04 +03:00
|
|
|
mkQId opVar colInfo = toJSONableExp strfyNum (pgiType colInfo) $
|
2018-10-09 09:39:20 +03:00
|
|
|
S.SEQIden $ S.QIden (opToQual opVar) $ toIden $ pgiName colInfo
|
|
|
|
|
|
|
|
opToQual = S.QualVar . opToTxt
|
|
|
|
opToTxt = T.pack . show
|
|
|
|
|
2018-10-25 10:22:51 +03:00
|
|
|
renderRow opVar scs =
|
|
|
|
case scs of
|
|
|
|
SubCStar -> applyRow $ S.SEUnsafe $ opToTxt opVar
|
|
|
|
SubCArray cols -> applyRow $
|
|
|
|
S.mkRowExp $ map (toExtr . mkQId opVar) $
|
|
|
|
getColInfos cols allCols
|
|
|
|
|
|
|
|
fromMaybePayload = fromMaybe SubCStar
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2019-05-13 12:41:07 +03:00
|
|
|
mkAllTriggersQ
|
2019-03-25 20:10:52 +03:00
|
|
|
:: TriggerName
|
2018-09-05 14:26:46 +03:00
|
|
|
-> QualifiedTable
|
2018-10-09 09:39:20 +03:00
|
|
|
-> [PGColInfo]
|
2019-03-01 14:45:04 +03:00
|
|
|
-> Bool
|
2018-09-05 14:26:46 +03:00
|
|
|
-> TriggerOpsDef
|
|
|
|
-> Q.TxE QErr ()
|
2019-05-13 12:41:07 +03:00
|
|
|
mkAllTriggersQ trn qt allCols strfyNum fullspec = do
|
|
|
|
let insertDef = tdInsert fullspec
|
|
|
|
updateDef = tdUpdate fullspec
|
|
|
|
deleteDef = tdDelete fullspec
|
|
|
|
onJust insertDef (mkTriggerQ trn qt allCols strfyNum INSERT)
|
|
|
|
onJust updateDef (mkTriggerQ trn qt allCols strfyNum UPDATE)
|
|
|
|
onJust deleteDef (mkTriggerQ trn qt allCols strfyNum DELETE)
|
|
|
|
|
|
|
|
mkTriggerQ
|
|
|
|
:: TriggerName
|
|
|
|
-> QualifiedTable
|
|
|
|
-> [PGColInfo]
|
|
|
|
-> Bool
|
|
|
|
-> Ops
|
|
|
|
-> SubscribeOpSpec
|
|
|
|
-> Q.TxE QErr ()
|
|
|
|
mkTriggerQ trn qt allCols strfyNum op spec = do
|
|
|
|
let mTriggerSql = getTriggerSql op trn qt allCols strfyNum spec
|
|
|
|
case mTriggerSql of
|
2018-10-19 05:15:28 +03:00
|
|
|
Just sql -> Q.multiQE defaultTxErrorHandler (Q.fromText sql)
|
2018-10-25 10:22:51 +03:00
|
|
|
Nothing -> throw500 "no trigger sql generated"
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2018-12-15 08:05:29 +03:00
|
|
|
delTriggerQ :: TriggerName -> Q.TxE QErr ()
|
|
|
|
delTriggerQ trn = mapM_ (\op -> Q.unitQE
|
|
|
|
defaultTxErrorHandler
|
|
|
|
(Q.fromText $ getDropFuncSql op trn) () False) [INSERT, UPDATE, DELETE]
|
|
|
|
|
2018-10-09 09:39:20 +03:00
|
|
|
addEventTriggerToCatalog
|
|
|
|
:: QualifiedTable
|
|
|
|
-> [PGColInfo]
|
2019-03-01 14:45:04 +03:00
|
|
|
-> Bool
|
2018-11-14 10:13:01 +03:00
|
|
|
-> EventTriggerConf
|
2019-03-25 20:10:52 +03:00
|
|
|
-> Q.TxE QErr ()
|
2019-03-01 14:45:04 +03:00
|
|
|
addEventTriggerToCatalog qt allCols strfyNum etc = do
|
2019-03-25 20:10:52 +03:00
|
|
|
Q.unitQE defaultTxErrorHandler
|
2018-12-13 10:26:15 +03:00
|
|
|
[Q.sql|
|
|
|
|
INSERT into hdb_catalog.event_triggers
|
|
|
|
(name, type, schema_name, table_name, configuration)
|
|
|
|
VALUES ($1, 'table', $2, $3, $4)
|
2019-03-25 20:10:52 +03:00
|
|
|
|] (name, sn, tn, Q.AltJ $ toJSON etc) True
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2019-05-13 12:41:07 +03:00
|
|
|
mkAllTriggersQ name qt allCols strfyNum fullspec
|
2018-09-05 14:26:46 +03:00
|
|
|
where
|
2019-01-25 06:31:54 +03:00
|
|
|
QualifiedObject sn tn = qt
|
2019-05-13 12:41:07 +03:00
|
|
|
(EventTriggerConf name fullspec _ _ _ _) = etc
|
2018-09-05 14:26:46 +03:00
|
|
|
|
|
|
|
delEventTriggerFromCatalog :: TriggerName -> Q.TxE QErr ()
|
|
|
|
delEventTriggerFromCatalog trn = do
|
|
|
|
Q.unitQE defaultTxErrorHandler [Q.sql|
|
|
|
|
DELETE FROM
|
|
|
|
hdb_catalog.event_triggers
|
|
|
|
WHERE name = $1
|
|
|
|
|] (Identity trn) True
|
2018-12-15 08:05:29 +03:00
|
|
|
delTriggerQ trn
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2018-09-19 15:12:57 +03:00
|
|
|
updateEventTriggerToCatalog
|
|
|
|
:: QualifiedTable
|
2018-10-09 09:39:20 +03:00
|
|
|
-> [PGColInfo]
|
2019-03-01 14:45:04 +03:00
|
|
|
-> Bool
|
2018-11-14 10:13:01 +03:00
|
|
|
-> EventTriggerConf
|
2019-03-25 20:10:52 +03:00
|
|
|
-> Q.TxE QErr ()
|
2019-03-01 14:45:04 +03:00
|
|
|
updateEventTriggerToCatalog qt allCols strfyNum etc = do
|
2019-04-05 15:20:46 +03:00
|
|
|
updateEventTriggerDef name etc
|
2018-12-15 08:05:29 +03:00
|
|
|
delTriggerQ name
|
2019-05-13 12:41:07 +03:00
|
|
|
mkAllTriggersQ name qt allCols strfyNum fullspec
|
|
|
|
where
|
|
|
|
EventTriggerConf name fullspec _ _ _ _ = etc
|
2018-09-19 15:12:57 +03:00
|
|
|
|
2018-09-07 14:51:01 +03:00
|
|
|
fetchEvent :: EventId -> Q.TxE QErr (EventId, Bool)
|
|
|
|
fetchEvent eid = do
|
2018-12-13 10:26:15 +03:00
|
|
|
events <- Q.listQE defaultTxErrorHandler
|
|
|
|
[Q.sql|
|
|
|
|
SELECT l.id, l.locked
|
|
|
|
FROM hdb_catalog.event_log l
|
|
|
|
JOIN hdb_catalog.event_triggers e
|
2019-03-25 20:10:52 +03:00
|
|
|
ON l.trigger_name = e.name
|
2018-12-13 10:26:15 +03:00
|
|
|
WHERE l.id = $1
|
|
|
|
|] (Identity eid) True
|
2018-09-07 14:51:01 +03:00
|
|
|
event <- getEvent events
|
|
|
|
assertEventUnlocked event
|
|
|
|
return event
|
|
|
|
where
|
|
|
|
getEvent [] = throw400 NotExists "event not found"
|
|
|
|
getEvent (x:_) = return x
|
|
|
|
|
|
|
|
assertEventUnlocked (_, locked) = when locked $
|
|
|
|
throw400 Busy "event is already being processed"
|
|
|
|
|
|
|
|
markForDelivery :: EventId -> Q.TxE QErr ()
|
|
|
|
markForDelivery eid =
|
|
|
|
Q.unitQE defaultTxErrorHandler [Q.sql|
|
|
|
|
UPDATE hdb_catalog.event_log
|
|
|
|
SET
|
|
|
|
delivered = 'f',
|
|
|
|
error = 'f',
|
|
|
|
tries = 0
|
|
|
|
WHERE id = $1
|
|
|
|
|] (Identity eid) True
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
subTableP1 :: (UserInfoM m, QErrM m, CacheRM m) => CreateEventTriggerQuery -> m (QualifiedTable, Bool, EventTriggerConf)
|
2019-05-13 12:41:07 +03:00
|
|
|
subTableP1 (CreateEventTriggerQuery name qt insert update delete enableManual retryConf webhook webhookFromEnv mheaders replace) = do
|
2018-09-07 14:51:01 +03:00
|
|
|
adminOnly
|
2018-09-05 14:26:46 +03:00
|
|
|
ti <- askTabInfo qt
|
2018-09-19 15:12:57 +03:00
|
|
|
-- can only replace for same table
|
|
|
|
when replace $ do
|
|
|
|
ti' <- askTabInfoFromTrigger name
|
|
|
|
when (tiName ti' /= tiName ti) $ throw400 NotSupported "cannot replace table or schema for trigger"
|
|
|
|
|
2018-09-05 14:26:46 +03:00
|
|
|
assertCols ti insert
|
|
|
|
assertCols ti update
|
|
|
|
assertCols ti delete
|
2018-09-19 15:12:57 +03:00
|
|
|
|
2019-02-14 10:37:59 +03:00
|
|
|
let rconf = fromMaybe defaultRetryConf retryConf
|
2019-05-13 12:41:07 +03:00
|
|
|
return (qt, replace, EventTriggerConf name (TriggerOpsDef insert update delete enableManual) webhook webhookFromEnv rconf mheaders)
|
2018-09-05 14:26:46 +03:00
|
|
|
where
|
|
|
|
assertCols _ Nothing = return ()
|
|
|
|
assertCols ti (Just sos) = do
|
|
|
|
let cols = sosColumns sos
|
|
|
|
case cols of
|
|
|
|
SubCStar -> return ()
|
|
|
|
SubCArray pgcols -> forM_ pgcols (assertPGCol (tiFieldInfoMap ti) "")
|
|
|
|
|
2018-11-23 16:02:46 +03:00
|
|
|
--(QErrM m, CacheRWM m, MonadTx m, MonadIO m)
|
|
|
|
|
|
|
|
subTableP2Setup
|
2018-12-13 10:26:15 +03:00
|
|
|
:: (QErrM m, CacheRWM m, MonadIO m)
|
2019-03-25 20:10:52 +03:00
|
|
|
=> QualifiedTable -> EventTriggerConf -> m ()
|
|
|
|
subTableP2Setup qt (EventTriggerConf name def webhook webhookFromEnv rconf mheaders) = do
|
2018-11-14 10:13:01 +03:00
|
|
|
webhookConf <- case (webhook, webhookFromEnv) of
|
|
|
|
(Just w, Nothing) -> return $ WCValue w
|
|
|
|
(Nothing, Just wEnv) -> return $ WCEnv wEnv
|
|
|
|
_ -> throw500 "expected webhook or webhook_from_env"
|
|
|
|
let headerConfs = fromMaybe [] mheaders
|
|
|
|
webhookInfo <- getWebhookInfoFromConf webhookConf
|
|
|
|
headerInfos <- getHeaderInfosFromConf headerConfs
|
2019-03-25 20:10:52 +03:00
|
|
|
let eTrigInfo = EventTriggerInfo name def rconf webhookInfo headerInfos
|
2018-11-16 15:40:23 +03:00
|
|
|
tabDep = SchemaDependency (SOTable qt) "parent"
|
|
|
|
addEventTriggerToCache qt eTrigInfo (tabDep:getTrigDefDeps qt def)
|
|
|
|
|
|
|
|
getTrigDefDeps :: QualifiedTable -> TriggerOpsDef -> [SchemaDependency]
|
2019-05-13 12:41:07 +03:00
|
|
|
getTrigDefDeps qt (TriggerOpsDef mIns mUpd mDel _) =
|
2018-11-16 15:40:23 +03:00
|
|
|
mconcat $ catMaybes [ subsOpSpecDeps <$> mIns
|
|
|
|
, subsOpSpecDeps <$> mUpd
|
|
|
|
, subsOpSpecDeps <$> mDel
|
|
|
|
]
|
|
|
|
where
|
|
|
|
subsOpSpecDeps :: SubscribeOpSpec -> [SchemaDependency]
|
|
|
|
subsOpSpecDeps os =
|
|
|
|
let cols = getColsFromSub $ sosColumns os
|
|
|
|
colDeps = flip map cols $ \col ->
|
|
|
|
SchemaDependency (SOTableObj qt (TOCol col)) "column"
|
|
|
|
payload = maybe [] getColsFromSub (sosPayload os)
|
|
|
|
payloadDeps = flip map payload $ \col ->
|
|
|
|
SchemaDependency (SOTableObj qt (TOCol col)) "payload"
|
|
|
|
in colDeps <> payloadDeps
|
|
|
|
getColsFromSub sc = case sc of
|
|
|
|
SubCStar -> []
|
|
|
|
SubCArray pgcols -> pgcols
|
2018-11-14 10:13:01 +03:00
|
|
|
|
2018-11-23 16:02:46 +03:00
|
|
|
subTableP2
|
2019-03-01 14:45:04 +03:00
|
|
|
:: (QErrM m, CacheRWM m, MonadTx m, MonadIO m, HasSQLGenCtx m)
|
2018-11-23 16:02:46 +03:00
|
|
|
=> QualifiedTable -> Bool -> EventTriggerConf -> m ()
|
2018-11-14 10:13:01 +03:00
|
|
|
subTableP2 qt replace etc = do
|
2018-10-25 10:22:51 +03:00
|
|
|
allCols <- getCols . tiFieldInfoMap <$> askTabInfo qt
|
2019-03-01 14:45:04 +03:00
|
|
|
strfyNum <- stringifyNum <$> askSQLGenCtx
|
2019-03-25 20:10:52 +03:00
|
|
|
if replace
|
2018-09-19 15:12:57 +03:00
|
|
|
then do
|
2018-11-14 10:13:01 +03:00
|
|
|
delEventTriggerFromCache qt (etcName etc)
|
2019-03-01 14:45:04 +03:00
|
|
|
liftTx $ updateEventTriggerToCatalog qt allCols strfyNum etc
|
2018-09-19 15:12:57 +03:00
|
|
|
else
|
2019-03-01 14:45:04 +03:00
|
|
|
liftTx $ addEventTriggerToCatalog qt allCols strfyNum etc
|
2019-03-25 20:10:52 +03:00
|
|
|
subTableP2Setup qt etc
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
runCreateEventTriggerQuery
|
2019-03-01 14:45:04 +03:00
|
|
|
:: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m, MonadIO m, HasSQLGenCtx m)
|
2019-03-18 19:22:21 +03:00
|
|
|
=> CreateEventTriggerQuery -> m EncJSON
|
2018-12-13 10:26:15 +03:00
|
|
|
runCreateEventTriggerQuery q = do
|
|
|
|
(qt, replace, etc) <- subTableP1 q
|
2018-11-14 10:13:01 +03:00
|
|
|
subTableP2 qt replace etc
|
2018-09-05 14:26:46 +03:00
|
|
|
return successMsg
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
unsubTableP1
|
|
|
|
:: (UserInfoM m, QErrM m, CacheRM m)
|
|
|
|
=> DeleteEventTriggerQuery -> m QualifiedTable
|
2018-09-19 15:12:57 +03:00
|
|
|
unsubTableP1 (DeleteEventTriggerQuery name) = do
|
|
|
|
adminOnly
|
|
|
|
ti <- askTabInfoFromTrigger name
|
|
|
|
return $ tiName ti
|
2018-09-05 14:26:46 +03:00
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
unsubTableP2
|
|
|
|
:: (QErrM m, CacheRWM m, MonadTx m)
|
2019-03-18 19:22:21 +03:00
|
|
|
=> DeleteEventTriggerQuery -> QualifiedTable -> m EncJSON
|
2018-12-13 10:26:15 +03:00
|
|
|
unsubTableP2 (DeleteEventTriggerQuery name) qt = do
|
2018-09-19 15:12:57 +03:00
|
|
|
delEventTriggerFromCache qt name
|
2018-09-05 14:26:46 +03:00
|
|
|
liftTx $ delEventTriggerFromCatalog name
|
|
|
|
return successMsg
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
runDeleteEventTriggerQuery
|
|
|
|
:: (QErrM m, UserInfoM m, CacheRWM m, MonadTx m)
|
2019-03-18 19:22:21 +03:00
|
|
|
=> DeleteEventTriggerQuery -> m EncJSON
|
2018-12-13 10:26:15 +03:00
|
|
|
runDeleteEventTriggerQuery q =
|
|
|
|
unsubTableP1 q >>= unsubTableP2 q
|
2018-09-07 14:51:01 +03:00
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
deliverEvent
|
|
|
|
:: (QErrM m, MonadTx m)
|
2019-05-13 12:41:07 +03:00
|
|
|
=> RedeliverEventQuery -> m EncJSON
|
|
|
|
deliverEvent (RedeliverEventQuery eventId) = do
|
2018-09-07 14:51:01 +03:00
|
|
|
_ <- liftTx $ fetchEvent eventId
|
|
|
|
liftTx $ markForDelivery eventId
|
|
|
|
return successMsg
|
|
|
|
|
2019-05-13 12:41:07 +03:00
|
|
|
runRedeliverEvent
|
2018-12-13 10:26:15 +03:00
|
|
|
:: (QErrM m, UserInfoM m, MonadTx m)
|
2019-05-13 12:41:07 +03:00
|
|
|
=> RedeliverEventQuery -> m EncJSON
|
|
|
|
runRedeliverEvent q =
|
2018-12-13 10:26:15 +03:00
|
|
|
adminOnly >> deliverEvent q
|
2018-09-19 15:12:57 +03:00
|
|
|
|
2019-05-13 12:41:07 +03:00
|
|
|
insertManualEvent
|
|
|
|
:: QualifiedTable
|
|
|
|
-> TriggerName
|
|
|
|
-> Value
|
|
|
|
-> Q.TxE QErr EventId
|
|
|
|
insertManualEvent qt trn rowData = do
|
|
|
|
let op = T.pack $ show MANUAL
|
|
|
|
eids <- map runIdentity <$> Q.listQE defaultTxErrorHandler [Q.sql|
|
|
|
|
SELECT hdb_catalog.insert_event_log($1, $2, $3, $4, $5)
|
|
|
|
|] (sn, tn, trn, op, Q.AltJ $ toJSON rowData) True
|
|
|
|
getEid eids
|
|
|
|
where
|
|
|
|
QualifiedObject sn tn = qt
|
|
|
|
getEid [] = throw500 "could not create manual event"
|
|
|
|
getEid (x:_) = return x
|
|
|
|
|
|
|
|
runInvokeEventTrigger
|
|
|
|
:: (QErrM m, UserInfoM m, CacheRM m, MonadTx m)
|
|
|
|
=> InvokeEventTriggerQuery -> m EncJSON
|
|
|
|
runInvokeEventTrigger (InvokeEventTriggerQuery name payload) = do
|
|
|
|
adminOnly
|
|
|
|
trigInfo <- askEventTriggerInfo name
|
|
|
|
assertManual $ etiOpsDef trigInfo
|
|
|
|
ti <- askTabInfoFromTrigger name
|
|
|
|
eid <-liftTx $ insertManualEvent (tiName ti) name payload
|
|
|
|
return $ encJFromJValue $ object ["event_id" .= eid]
|
|
|
|
where
|
|
|
|
assertManual (TriggerOpsDef _ _ _ man) = case man of
|
|
|
|
Just True -> return ()
|
|
|
|
_ -> throw400 NotSupported "manual mode is not enabled for event trigger"
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
getHeaderInfosFromConf
|
|
|
|
:: (QErrM m, MonadIO m)
|
|
|
|
=> [HeaderConf] -> m [EventHeaderInfo]
|
2018-10-26 19:28:03 +03:00
|
|
|
getHeaderInfosFromConf = mapM getHeader
|
2018-09-24 14:50:11 +03:00
|
|
|
where
|
2018-11-23 16:02:46 +03:00
|
|
|
getHeader :: (QErrM m, MonadIO m) => HeaderConf -> m EventHeaderInfo
|
2018-09-24 14:50:11 +03:00
|
|
|
getHeader hconf = case hconf of
|
2018-10-26 19:28:03 +03:00
|
|
|
(HeaderConf _ (HVValue val)) -> return $ EventHeaderInfo hconf val
|
|
|
|
(HeaderConf _ (HVEnv val)) -> do
|
2018-11-14 10:13:01 +03:00
|
|
|
envVal <- getEnv val
|
|
|
|
return $ EventHeaderInfo hconf envVal
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
getWebhookInfoFromConf
|
|
|
|
:: (QErrM m, MonadIO m) => WebhookConf -> m WebhookConfInfo
|
2018-11-14 10:13:01 +03:00
|
|
|
getWebhookInfoFromConf wc = case wc of
|
|
|
|
WCValue w -> return $ WebhookConfInfo wc w
|
|
|
|
WCEnv we -> do
|
|
|
|
envVal <- getEnv we
|
|
|
|
return $ WebhookConfInfo wc envVal
|
|
|
|
|
|
|
|
getEnv :: (QErrM m, MonadIO m) => T.Text -> m T.Text
|
|
|
|
getEnv env = do
|
2018-12-13 10:26:15 +03:00
|
|
|
mEnv <- liftIO $ lookupEnv (T.unpack env)
|
|
|
|
case mEnv of
|
|
|
|
Nothing -> throw400 NotFound $ "environment variable '" <> env <> "' not set"
|
|
|
|
Just envVal -> return (T.pack envVal)
|
2019-03-01 16:59:24 +03:00
|
|
|
|
|
|
|
getEventTriggerDef
|
|
|
|
:: TriggerName
|
|
|
|
-> Q.TxE QErr (QualifiedTable, EventTriggerConf)
|
|
|
|
getEventTriggerDef triggerName = do
|
|
|
|
(sn, tn, Q.AltJ etc) <- Q.getRow <$> Q.withQE defaultTxErrorHandler
|
|
|
|
[Q.sql|
|
|
|
|
SELECT e.schema_name, e.table_name, e.configuration::json
|
|
|
|
FROM hdb_catalog.event_triggers e where e.name = $1
|
|
|
|
|] (Identity triggerName) False
|
|
|
|
return (QualifiedObject sn tn, etc)
|
|
|
|
|
|
|
|
updateEventTriggerDef
|
2019-03-25 20:10:52 +03:00
|
|
|
:: TriggerName -> EventTriggerConf -> Q.TxE QErr ()
|
2019-03-01 16:59:24 +03:00
|
|
|
updateEventTriggerDef trigName trigConf =
|
2019-03-25 20:10:52 +03:00
|
|
|
Q.unitQE defaultTxErrorHandler
|
2019-03-01 16:59:24 +03:00
|
|
|
[Q.sql|
|
|
|
|
UPDATE hdb_catalog.event_triggers
|
|
|
|
SET
|
|
|
|
configuration = $1
|
|
|
|
WHERE name = $2
|
2019-03-25 20:10:52 +03:00
|
|
|
|] (Q.AltJ $ toJSON trigConf, trigName) True
|