From a5d7f71150c18aad5536cf6ebc5088e35b00f6c6 Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Thu, 10 Sep 2020 14:21:45 +0530 Subject: [PATCH 1/7] accept configurable timeouts for actions --- .../src-lib/Hasura/GraphQL/Execute/Action.hs | 22 ++++++++++++------- .../src-lib/Hasura/GraphQL/Schema/Action.hs | 1 + server/src-lib/Hasura/RQL/DDL/Action.hs | 2 +- .../src-lib/Hasura/RQL/DDL/Metadata/Types.hs | 4 +++- server/src-lib/Hasura/RQL/Types/Action.hs | 16 +++++++++++--- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Execute/Action.hs b/server/src-lib/Hasura/GraphQL/Execute/Action.hs index d9c23475c143f..ecf54fdd71ffd 100644 --- a/server/src-lib/Hasura/GraphQL/Execute/Action.hs +++ b/server/src-lib/Hasura/GraphQL/Execute/Action.hs @@ -154,7 +154,7 @@ resolveActionExecution env logger userInfo annAction execContext = do let actionContext = ActionContext actionName handlerPayload = ActionWebhookPayload actionContext sessionVariables inputPayload (webhookRes, respHeaders) <- flip runReaderT logger $ callWebhook env manager outputType outputFields reqHeaders confHeaders - forwardClientHeaders resolvedWebhook handlerPayload + forwardClientHeaders resolvedWebhook handlerPayload timeout let webhookResponseExpression = RS.AEInput $ UVLiteral $ toTxtValue $ WithScalarType PGJSONB $ PGValJSONB $ Q.JSONB $ J.toJSON webhookRes selectAstUnresolved = processOutputSelectionSet webhookResponseExpression @@ -164,7 +164,7 @@ resolveActionExecution env logger userInfo annAction execContext = do where AnnActionExecution actionName outputType annFields inputPayload outputFields definitionList resolvedWebhook confHeaders - forwardClientHeaders stringifyNum = annAction + forwardClientHeaders stringifyNum timeout = annAction ActionExecContext manager reqHeaders sessionVariables = execContext @@ -331,12 +331,14 @@ asyncActionsProcessor env logger cacheRef pgPool httpManager = forever $ do webhookUrl = _adHandler definition forwardClientHeaders = _adForwardClientHeaders definition confHeaders = _adHeaders definition + timeout = _adTimeout definition outputType = _adOutputType definition actionContext = ActionContext actionName eitherRes <- runExceptT $ flip runReaderT logger $ callWebhook env httpManager outputType outputFields reqHeaders confHeaders - forwardClientHeaders webhookUrl $ - ActionWebhookPayload actionContext sessionVariables inputPayload + forwardClientHeaders webhookUrl (ActionWebhookPayload actionContext sessionVariables inputPayload) + timeout + liftIO $ case eitherRes of Left e -> setError actionId e Right (responsePayload, _) -> setCompleted actionId $ J.toJSON responsePayload @@ -408,9 +410,10 @@ callWebhook -> Bool -> ResolvedWebhook -> ActionWebhookPayload + -> Maybe Int -> m (ActionWebhookResponse, HTTP.ResponseHeaders) callWebhook env manager outputType outputFields reqHeaders confHeaders - forwardClientHeaders resolvedWebhook actionWebhookPayload = do + forwardClientHeaders resolvedWebhook actionWebhookPayload timeoutSeconds = do resolvedConfHeaders <- makeHeadersFromConf env confHeaders let clientHeaders = if forwardClientHeaders then mkClientHeadersForward reqHeaders else [] contentType = ("Content-Type", "application/json") @@ -421,11 +424,14 @@ callWebhook env manager outputType outputFields reqHeaders confHeaders requestBody = J.encode postPayload requestBodySize = BL.length requestBody url = unResolvedWebhook resolvedWebhook + responseTimeoutSec = fromMaybe defaultTimeoutSeconds $ timeoutSeconds + responseTimeout = HTTP.responseTimeoutMicro $ responseTimeoutSec * 1000000 httpResponse <- do initReq <- liftIO $ HTTP.parseRequest (T.unpack url) - let req = initReq { HTTP.method = "POST" - , HTTP.requestHeaders = addDefaultHeaders hdrs - , HTTP.requestBody = HTTP.RequestBodyLBS requestBody + let req = initReq { HTTP.method = "POST" + , HTTP.requestHeaders = addDefaultHeaders hdrs + , HTTP.requestBody = HTTP.RequestBodyLBS requestBody + , HTTP.responseTimeout = responseTimeout } Tracing.tracedHttpRequest req \req' -> liftIO . try $ HTTP.httpLbs req' manager diff --git a/server/src-lib/Hasura/GraphQL/Schema/Action.hs b/server/src-lib/Hasura/GraphQL/Schema/Action.hs index 7c99ac1489280..4f3b294ef6969 100644 --- a/server/src-lib/Hasura/GraphQL/Schema/Action.hs +++ b/server/src-lib/Hasura/GraphQL/Schema/Action.hs @@ -62,6 +62,7 @@ actionExecute nonObjectTypeMap actionInfo = runMaybeT do , _aaeHeaders = _adHeaders definition , _aaeForwardClientHeaders = _adForwardClientHeaders definition , _aaeStrfyNum = stringifyNum + , _aaeTimeOut = _adTimeout definition } where ActionInfo actionName outputObject definition permissions comment = actionInfo diff --git a/server/src-lib/Hasura/RQL/DDL/Action.hs b/server/src-lib/Hasura/RQL/DDL/Action.hs index 7ac5d3fc857ed..96364b047c861 100644 --- a/server/src-lib/Hasura/RQL/DDL/Action.hs +++ b/server/src-lib/Hasura/RQL/DDL/Action.hs @@ -125,7 +125,7 @@ resolveAction env AnnotatedCustomTypes{..} ActionDefinition{..} allPGScalars = d <> " is not an object type defined in custom types" resolvedWebhook <- resolveWebhook env _adHandler pure ( ActionDefinition resolvedArguments _adOutputType _adType - _adHeaders _adForwardClientHeaders resolvedWebhook + _adHeaders _adForwardClientHeaders _adTimeout resolvedWebhook , outputObject ) diff --git a/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs b/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs index 4d1733e8d3b3a..57ac4d4c3bb9a 100644 --- a/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs +++ b/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs @@ -538,7 +538,8 @@ replaceMetadataToOrdJSON ( ReplaceMetadata <> catMaybes [maybeAnyToMaybeOrdPair "description" AO.toOrdered descM] actionDefinitionToOrdJSON :: ActionDefinitionInput -> AO.Value - actionDefinitionToOrdJSON (ActionDefinition args outputType actionType headers frwrdClientHdrs handler) = + actionDefinitionToOrdJSON (ActionDefinition args outputType actionType + headers frwrdClientHdrs timeout handler) = let typeAndKind = case actionType of ActionQuery -> [("type", AO.toOrdered ("query" :: String))] ActionMutation kind -> [ ("type", AO.toOrdered ("mutation" :: String)) @@ -551,6 +552,7 @@ replaceMetadataToOrdJSON ( ReplaceMetadata <> catMaybes [ listToMaybeOrdPair "headers" AO.toOrdered headers , listToMaybeOrdPair "arguments" argDefinitionToOrdJSON args] <> typeAndKind + <> catMaybes [ maybeAnyToMaybeOrdPair "timeout" AO.toOrdered timeout] permToOrdJSON :: ActionPermissionMetadata -> AO.Value permToOrdJSON (ActionPermissionMetadata role permComment) = diff --git a/server/src-lib/Hasura/RQL/Types/Action.hs b/server/src-lib/Hasura/RQL/Types/Action.hs index 92b85b14c4e1e..9ed998560b794 100644 --- a/server/src-lib/Hasura/RQL/Types/Action.hs +++ b/server/src-lib/Hasura/RQL/Types/Action.hs @@ -10,9 +10,10 @@ module Hasura.RQL.Types.Action , adArguments , adOutputType , adType - , adHeaders , adForwardClientHeaders + , adHeaders , adHandler + , adTimeout , ActionType(..) , _ActionMutation , CreateAction(..) @@ -122,6 +123,9 @@ data ActionDefinition a b , _adType :: !ActionType , _adHeaders :: ![HeaderConf] , _adForwardClientHeaders :: !Bool + , _adTimeout :: !(Maybe Int) + -- ^ If the timeout is not provided by the user, then + -- the default timeout of Network.HTTP.Client (30 seconds) will be used , _adHandler :: !b } deriving (Show, Eq, Lift, Functor, Foldable, Traversable, Generic) instance (NFData a, NFData b) => NFData (ActionDefinition a b) @@ -135,6 +139,11 @@ instance (J.FromJSON a, J.FromJSON b) => J.FromJSON (ActionDefinition a b) where _adHeaders <- o J..:? "headers" J..!= [] _adForwardClientHeaders <- o J..:? "forward_client_headers" J..!= False _adHandler <- o J..: "handler" + timeout <- o J..:? "timeout" + _adTimeout <- case timeout of + Nothing -> pure Nothing + Just t -> + bool (fail "timeout cannot be a negative value") (pure $ Just t) $ t > 0 actionType <- o J..:? "type" J..!= "mutation" _adType <- case actionType of "mutation" -> ActionMutation <$> o J..:? "kind" J..!= ActionSynchronous @@ -143,7 +152,7 @@ instance (J.FromJSON a, J.FromJSON b) => J.FromJSON (ActionDefinition a b) where return ActionDefinition {..} instance (J.ToJSON a, J.ToJSON b) => J.ToJSON (ActionDefinition a b) where - toJSON (ActionDefinition args outputType actionType headers forwardClientHeaders handler) = + toJSON (ActionDefinition args outputType actionType headers forwardClientHeaders timeout handler) = let typeAndKind = case actionType of ActionQuery -> [ "type" J..= ("query" :: String)] ActionMutation kind -> [ "type" J..= ("mutation" :: String) @@ -154,7 +163,7 @@ instance (J.ToJSON a, J.ToJSON b) => J.ToJSON (ActionDefinition a b) where , "headers" J..= headers , "forward_client_headers" J..= forwardClientHeaders , "handler" J..= handler - ] <> typeAndKind + ] <> typeAndKind <> (maybe mempty (\t -> ["timeout" J..= t]) timeout) type ResolvedActionDefinition = ActionDefinition (ArgumentDefinition (G.GType, NonObjectCustomType)) ResolvedWebhook @@ -262,6 +271,7 @@ data AnnActionExecution v , _aaeHeaders :: ![HeaderConf] , _aaeForwardClientHeaders :: !Bool , _aaeStrfyNum :: !Bool + , _aaeTimeOut :: !(Maybe Int) } deriving (Show, Eq) data AnnActionMutationAsync From 1b533e9a750bc7f566fff7c62cec1ffdbaa68ab3 Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Thu, 10 Sep 2020 16:16:06 +0530 Subject: [PATCH 2/7] create a newtype Timeout --- .../src-lib/Hasura/GraphQL/Execute/Action.hs | 5 ++--- .../src-lib/Hasura/RQL/DDL/Metadata/Types.hs | 2 +- server/src-lib/Hasura/RQL/Types/Action.hs | 16 +++++++-------- server/src-lib/Hasura/RQL/Types/Common.hs | 20 +++++++++++++++++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/server/src-lib/Hasura/GraphQL/Execute/Action.hs b/server/src-lib/Hasura/GraphQL/Execute/Action.hs index ecf54fdd71ffd..a9a3b716de937 100644 --- a/server/src-lib/Hasura/GraphQL/Execute/Action.hs +++ b/server/src-lib/Hasura/GraphQL/Execute/Action.hs @@ -410,7 +410,7 @@ callWebhook -> Bool -> ResolvedWebhook -> ActionWebhookPayload - -> Maybe Int + -> Timeout -> m (ActionWebhookResponse, HTTP.ResponseHeaders) callWebhook env manager outputType outputFields reqHeaders confHeaders forwardClientHeaders resolvedWebhook actionWebhookPayload timeoutSeconds = do @@ -424,8 +424,7 @@ callWebhook env manager outputType outputFields reqHeaders confHeaders requestBody = J.encode postPayload requestBodySize = BL.length requestBody url = unResolvedWebhook resolvedWebhook - responseTimeoutSec = fromMaybe defaultTimeoutSeconds $ timeoutSeconds - responseTimeout = HTTP.responseTimeoutMicro $ responseTimeoutSec * 1000000 + responseTimeout = HTTP.responseTimeoutMicro $ (unTimeout timeoutSeconds) * 1000000 httpResponse <- do initReq <- liftIO $ HTTP.parseRequest (T.unpack url) let req = initReq { HTTP.method = "POST" diff --git a/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs b/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs index 57ac4d4c3bb9a..7c79c3959bfb5 100644 --- a/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs +++ b/server/src-lib/Hasura/RQL/DDL/Metadata/Types.hs @@ -552,7 +552,7 @@ replaceMetadataToOrdJSON ( ReplaceMetadata <> catMaybes [ listToMaybeOrdPair "headers" AO.toOrdered headers , listToMaybeOrdPair "arguments" argDefinitionToOrdJSON args] <> typeAndKind - <> catMaybes [ maybeAnyToMaybeOrdPair "timeout" AO.toOrdered timeout] + <> (bool [("timeout",AO.toOrdered timeout)] mempty $ timeout == defaultActionTimeoutSecs) permToOrdJSON :: ActionPermissionMetadata -> AO.Value permToOrdJSON (ActionPermissionMetadata role permComment) = diff --git a/server/src-lib/Hasura/RQL/Types/Action.hs b/server/src-lib/Hasura/RQL/Types/Action.hs index 9ed998560b794..9718deaabadf4 100644 --- a/server/src-lib/Hasura/RQL/Types/Action.hs +++ b/server/src-lib/Hasura/RQL/Types/Action.hs @@ -32,6 +32,7 @@ module Hasura.RQL.Types.Action , aiDefinition , aiPermissions , aiComment + , defaultActionTimeoutSecs , ActionPermissionInfo(..) , ActionPermissionMap @@ -123,9 +124,9 @@ data ActionDefinition a b , _adType :: !ActionType , _adHeaders :: ![HeaderConf] , _adForwardClientHeaders :: !Bool - , _adTimeout :: !(Maybe Int) + , _adTimeout :: !Timeout -- ^ If the timeout is not provided by the user, then - -- the default timeout of Network.HTTP.Client (30 seconds) will be used + -- the default timeout of 30 seconds will be used , _adHandler :: !b } deriving (Show, Eq, Lift, Functor, Foldable, Traversable, Generic) instance (NFData a, NFData b) => NFData (ActionDefinition a b) @@ -139,11 +140,7 @@ instance (J.FromJSON a, J.FromJSON b) => J.FromJSON (ActionDefinition a b) where _adHeaders <- o J..:? "headers" J..!= [] _adForwardClientHeaders <- o J..:? "forward_client_headers" J..!= False _adHandler <- o J..: "handler" - timeout <- o J..:? "timeout" - _adTimeout <- case timeout of - Nothing -> pure Nothing - Just t -> - bool (fail "timeout cannot be a negative value") (pure $ Just t) $ t > 0 + _adTimeout <- o J..:? "timeout" J..!= defaultActionTimeoutSecs actionType <- o J..:? "type" J..!= "mutation" _adType <- case actionType of "mutation" -> ActionMutation <$> o J..:? "kind" J..!= ActionSynchronous @@ -163,7 +160,8 @@ instance (J.ToJSON a, J.ToJSON b) => J.ToJSON (ActionDefinition a b) where , "headers" J..= headers , "forward_client_headers" J..= forwardClientHeaders , "handler" J..= handler - ] <> typeAndKind <> (maybe mempty (\t -> ["timeout" J..= t]) timeout) + , "timeout" J..= timeout + ] <> typeAndKind type ResolvedActionDefinition = ActionDefinition (ArgumentDefinition (G.GType, NonObjectCustomType)) ResolvedWebhook @@ -271,7 +269,7 @@ data AnnActionExecution v , _aaeHeaders :: ![HeaderConf] , _aaeForwardClientHeaders :: !Bool , _aaeStrfyNum :: !Bool - , _aaeTimeOut :: !(Maybe Int) + , _aaeTimeOut :: !Timeout } deriving (Show, Eq) data AnnActionMutationAsync diff --git a/server/src-lib/Hasura/RQL/Types/Common.hs b/server/src-lib/Hasura/RQL/Types/Common.hs index abbbe4d3f555a..4e669a912e27b 100644 --- a/server/src-lib/Hasura/RQL/Types/Common.hs +++ b/server/src-lib/Hasura/RQL/Types/Common.hs @@ -41,6 +41,9 @@ module Hasura.RQL.Types.Common , InputWebhook(..) , ResolvedWebhook(..) , resolveWebhook + + , Timeout(..) + , defaultActionTimeoutSecs ) where import Hasura.EncJSON @@ -57,6 +60,7 @@ import Control.Lens (makeLenses) import Data.Aeson import Data.Aeson.Casing import Data.Aeson.TH +import Data.Scientific (toBoundedInteger) import Data.URL.Template import Instances.TH.Lift () import Language.Haskell.TH.Syntax (Lift, Q, TExp) @@ -310,3 +314,19 @@ resolveWebhook env (InputWebhook urlTemplate) = do let eitherRenderedTemplate = renderURLTemplate env urlTemplate either (throw400 Unexpected . T.pack) (pure . ResolvedWebhook) eitherRenderedTemplate + +newtype Timeout = Timeout { unTimeout :: Int } + deriving (Show, Eq, ToJSON, Generic, NFData, Cacheable, Lift) + +instance FromJSON Timeout where + parseJSON = withScientific "Timeout" $ \t -> do + timeout <- onNothing (toBoundedInteger t) $ fail (show t <> " is out of bounds") + case (timeout >= 0) of + True -> return $ Timeout timeout + False -> fail "timeout value cannot be negative" + +instance Arbitrary Timeout where + arbitrary = Timeout <$> QC.choose (0, 10000000) + +defaultActionTimeoutSecs :: Timeout +defaultActionTimeoutSecs = Timeout 30 From 5d74c0532e96ea2fb0fb88725a74a97af215f046 Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Thu, 10 Sep 2020 16:29:45 +0530 Subject: [PATCH 3/7] update CHANGELOG and add docs --- CHANGELOG.md | 1 + .../core/api-reference/schema-metadata-api/actions.rst | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index acbddded4acfa..3c6ff5b0a2528 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph - server: miscellaneous description changes (#4111) - server: treat the absence of `backend_only` configuration and `backend_only: false` equally (closing #5059) (#4111) - server: allow remote relationships joining `type` column with `[type]` input argument as spec allows this coercion (fixes #5133) +- server: allow adding custom timeouts to actions (fixes #4966) - console: allow user to cascade Postgres dependencies when dropping Postgres objects (close #5109) (#5248) - console: mark inconsistent remote schemas in the UI (close #5093) (#5181) - cli: add missing global flags for seeds command (#5565) diff --git a/docs/graphql/core/api-reference/schema-metadata-api/actions.rst b/docs/graphql/core/api-reference/schema-metadata-api/actions.rst index fded740e32bac..68b9c810be939 100644 --- a/docs/graphql/core/api-reference/schema-metadata-api/actions.rst +++ b/docs/graphql/core/api-reference/schema-metadata-api/actions.rst @@ -49,7 +49,8 @@ Create a synchronous action with name ``create_user``: } ], "output_type":"User", - "handler":"https://action.my_app.com/create-user" + "handler":"https://action.my_app.com/create-user", + "timeout":60 }, "comment": "Custom action to create user" } @@ -122,6 +123,11 @@ ActionDefinition - false - [ ``mutation`` | ``query`` ] - The type of the action (default: ``mutation``) + * - timeout + - false + - Integer + - Number of seconds to wait for response before timing out. Default: 30 + .. _InputArgument: From 7228d597bff2e654167d8013c8db87136036be0f Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Thu, 10 Sep 2020 20:54:02 +0530 Subject: [PATCH 4/7] add timeout test for actions --- server/tests-py/context.py | 5 ++++ server/tests-py/test_actions.py | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/server/tests-py/context.py b/server/tests-py/context.py index b31ce970cacd3..6e838372dce73 100644 --- a/server/tests-py/context.py +++ b/server/tests-py/context.py @@ -179,6 +179,11 @@ def do_POST(self): resp, status = self.create_user() self._send_response(status, resp) + elif req_path == "/create-user-timeout": + time.sleep(2) + resp, status = self.create_user() + self._send_response(status, resp) + elif req_path == "/create-users": resp, status = self.create_users() self._send_response(status, resp) diff --git a/server/tests-py/test_actions.py b/server/tests-py/test_actions.py index 849a532bcb15f..9b602732cbfed 100644 --- a/server/tests-py/test_actions.py +++ b/server/tests-py/test_actions.py @@ -475,3 +475,50 @@ def test_introspection_query(self, hge_ctx): code, resp, _ = hge_ctx.anyq(conf['url'], conf['query'], headers) assert code == 200, resp assert 'data' in resp, resp + +@use_action_fixtures +class TestActionTimeout: + + @classmethod + def dir(cls): + return 'queries/actions/timeout' + + def test_action_timeout_fail(self, hge_ctx): + graphql_mutation = ''' + mutation { + create_user(email: "random-email", name: "Clarke") + } + ''' + query = { + 'query': graphql_mutation, + 'variables': {} + } + status, resp, _ = hge_ctx.anyq('/v1/graphql', query, mk_headers_with_secret(hge_ctx)) + assert status == 200, resp + assert 'data' in resp + action_id = resp['data']['create_user'] + query_async = ''' + query ($action_id: uuid!){ + create_user(id: $action_id){ + id + errors + } + } + ''' + query = { + 'query': query_async, + 'variables': { + 'action_id': action_id + } + } + conf = { + 'url': '/v1/graphql', + 'headers': {}, + 'query': query, + 'status': 200, + } + # the action takes 2 seconds to complete + time.sleep(3) + response, _ = check_query(hge_ctx, conf) + assert 'errors' in response['data']['create_user'] + assert 'ResponseTimeout' == response['data']['create_user']['errors']['internal']['error']['message'] From 13b96abde3a16627bf0c624b35e7364bc853c11e Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Tue, 15 Sep 2020 09:26:49 +0530 Subject: [PATCH 5/7] add test files for actions timeout --- .../queries/actions/timeout/schema_setup.yaml | 44 +++++++++++++++++++ .../actions/timeout/schema_teardown.yaml | 15 +++++++ .../actions/timeout/values_teardown.yaml | 7 +++ 3 files changed, 66 insertions(+) create mode 100644 server/tests-py/queries/actions/timeout/schema_setup.yaml create mode 100644 server/tests-py/queries/actions/timeout/schema_teardown.yaml create mode 100644 server/tests-py/queries/actions/timeout/values_teardown.yaml diff --git a/server/tests-py/queries/actions/timeout/schema_setup.yaml b/server/tests-py/queries/actions/timeout/schema_setup.yaml new file mode 100644 index 0000000000000..224c33e2b244f --- /dev/null +++ b/server/tests-py/queries/actions/timeout/schema_setup.yaml @@ -0,0 +1,44 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + CREATE TABLE "user"( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + email TEXT NOT NULL, + is_admin BOOLEAN NOT NULL DEFAULT false + ); + +- type: track_table + args: + name: user + schema: public + +- type: set_custom_types + args: + objects: + - name: UserId + fields: + - name: id + type: Int! + relationships: + - name: user + type: object + remote_table: user + field_mapping: + id: id + +- type: create_action + args: + name: create_user + definition: + kind: asynchronous + arguments: + - name: email + type: String! + - name: name + type: String! + output_type: UserId + timeout: 2 + handler: http://127.0.0.1:5593/create-user-timeout diff --git a/server/tests-py/queries/actions/timeout/schema_teardown.yaml b/server/tests-py/queries/actions/timeout/schema_teardown.yaml new file mode 100644 index 0000000000000..5b4bfc6d4a39a --- /dev/null +++ b/server/tests-py/queries/actions/timeout/schema_teardown.yaml @@ -0,0 +1,15 @@ +type: bulk +args: +- type: drop_action + args: + name: create_user + clear_data: true +# clear custom types +- type: set_custom_types + args: {} + +- type: run_sql + args: + cascade: true + sql: | + DROP TABLE "user"; diff --git a/server/tests-py/queries/actions/timeout/values_teardown.yaml b/server/tests-py/queries/actions/timeout/values_teardown.yaml new file mode 100644 index 0000000000000..f5acee6da0db4 --- /dev/null +++ b/server/tests-py/queries/actions/timeout/values_teardown.yaml @@ -0,0 +1,7 @@ +type: bulk +args: +- type: run_sql + args: + sql: | + DELETE FROM "user"; + SELECT setval('user_id_seq', 1, FALSE); From 4b805ade8a181dd280c353072ec6e212ed1ccf8d Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Wed, 16 Sep 2020 12:12:23 +0530 Subject: [PATCH 6/7] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 138796b38ab90..27ac5ad267711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,7 +56,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph - server: allow remote relationships joining `type` column with `[type]` input argument as spec allows this coercion (fixes #5133) - server: add action-like URL templating for event triggers and remote schemas (fixes #2483) - server: change `created_at` column type from `timestamp` to `timestamptz` for scheduled triggers tables (fix #5722) -- server: allow adding custom timeouts to actions (fixes #4966) +- server: allow configuring timeouts for actions (fixes #4966) - console: allow user to cascade Postgres dependencies when dropping Postgres objects (close #5109) (#5248) - console: mark inconsistent remote schemas in the UI (close #5093) (#5181) - cli: add missing global flags for seeds command (#5565) From c79e74e296d71c73680f47fd47d2aa8735834d95 Mon Sep 17 00:00:00 2001 From: Karthikeyan Chinnakonda Date: Wed, 16 Sep 2020 14:04:58 +0530 Subject: [PATCH 7/7] increase the timeout in the action test --- server/tests-py/test_actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/tests-py/test_actions.py b/server/tests-py/test_actions.py index 9b602732cbfed..7d462bc7fa360 100644 --- a/server/tests-py/test_actions.py +++ b/server/tests-py/test_actions.py @@ -518,7 +518,7 @@ def test_action_timeout_fail(self, hge_ctx): 'status': 200, } # the action takes 2 seconds to complete - time.sleep(3) + time.sleep(4) response, _ = check_query(hge_ctx, conf) assert 'errors' in response['data']['create_user'] assert 'ResponseTimeout' == response['data']['create_user']['errors']['internal']['error']['message']