Skip to content

Commit f39f1e2

Browse files
committed
fix(worker): handle exiting on 5xx errors
merged the common resolver handling code to a common worker function to reuse the code when we need to handle errors fixes #59
1 parent 62a9541 commit f39f1e2

File tree

4 files changed

+60
-45
lines changed

4 files changed

+60
-45
lines changed

.github/workflows/servc.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
push:
55

66
env:
7-
SERVC_VERSION: 0.5.0
7+
SERVC_VERSION: 0.5.1
88

99
permissions:
1010
contents: write

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
pip install -r requirements-dev.txt
5151
5252
- name: Type check
53-
run: mypy servc
53+
run: mypy servc --check-untyped-defs
5454

5555
- name: Run tests
5656
env:

servc/svc/com/worker/__init__.py

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
from typing import Any, List
1+
from typing import Any, List, Tuple
22

33
from servc.svc import ComponentType, Middleware
44
from servc.svc.com.bus import BusComponent, OnConsuming
55
from servc.svc.com.cache import CacheComponent
66
from servc.svc.com.worker.hooks import evaluate_post_hooks, evaluate_pre_hooks
7-
from servc.svc.com.worker.types import RESOLVER_CONTEXT, RESOLVER_MAPPING
7+
from servc.svc.com.worker.types import RESOLVER, RESOLVER_CONTEXT, RESOLVER_MAPPING
88
from servc.svc.config import Config
99
from servc.svc.io.input import InputType
1010
from servc.svc.io.output import (
1111
InvalidInputsException,
1212
MethodNotFoundException,
1313
NoProcessingException,
1414
NotAuthorizedException,
15+
ResponseArtifact,
1516
StatusCode,
1617
)
1718
from servc.svc.io.response import getAnswerArtifact, getErrorArtifact
@@ -102,6 +103,35 @@ def connect(self):
102103
bindEventExchange=self._bindToEventExchange,
103104
)
104105

106+
def run_resolver(
107+
self, method: RESOLVER, context: RESOLVER_CONTEXT, args: Tuple[str, Any]
108+
) -> Tuple[StatusCode, ResponseArtifact | None]:
109+
id, payload = args
110+
try:
111+
response = method(id, payload, context)
112+
return StatusCode.OK, getAnswerArtifact(id, response)
113+
except NotAuthorizedException as e:
114+
return StatusCode.NOT_AUTHORIZED, getErrorArtifact(
115+
id, str(e), StatusCode.NOT_AUTHORIZED
116+
)
117+
except InvalidInputsException as e:
118+
return StatusCode.INVALID_INPUTS, getErrorArtifact(
119+
id, str(e), StatusCode.INVALID_INPUTS
120+
)
121+
except NoProcessingException:
122+
return StatusCode.NO_PROCESSING, None
123+
except MethodNotFoundException as e:
124+
return StatusCode.METHOD_NOT_FOUND, getErrorArtifact(
125+
id, str(e), StatusCode.METHOD_NOT_FOUND
126+
)
127+
except Exception as e:
128+
if self._config.get(f"conf.{self.name}.exiton5xx"):
129+
print("Exiting due to 5xx error", e, flush=True)
130+
exit(1)
131+
return StatusCode.SERVER_ERROR, getErrorArtifact(
132+
id, str(e), StatusCode.SERVER_ERROR
133+
)
134+
105135
def inputProcessor(self, message: Any) -> StatusCode:
106136
bus = self._busClass(
107137
self._config.get(f"conf.{self._bus.name}"),
@@ -126,8 +156,14 @@ def inputProcessor(self, message: Any) -> StatusCode:
126156
return StatusCode.INVALID_INPUTS
127157
if message["event"] not in self._eventResolvers:
128158
return StatusCode.METHOD_NOT_FOUND
129-
self._eventResolvers[message["event"]]("", {**message}, context)
130-
return StatusCode.OK
159+
160+
status_code, response = self.run_resolver(
161+
self._eventResolvers[message["event"]],
162+
context,
163+
("", {**message}),
164+
)
165+
166+
return status_code
131167

132168
if message["type"] in [InputType.INPUT.value, InputType.INPUT]:
133169
if "id" not in message:
@@ -177,45 +213,17 @@ def inputProcessor(self, message: Any) -> StatusCode:
177213
if not continueExecution:
178214
return StatusCode.OK
179215

180-
statusCode: StatusCode = StatusCode.OK
181-
try:
182-
response = self._resolvers[artifact["method"]](
183-
message["id"],
184-
artifact["inputs"],
185-
context,
186-
)
187-
cache.setKey(message["id"], getAnswerArtifact(message["id"], response))
188-
except NotAuthorizedException as e:
189-
cache.setKey(
190-
message["id"],
191-
getErrorArtifact(message["id"], str(e), StatusCode.NOT_AUTHORIZED),
192-
)
193-
statusCode = StatusCode.NOT_AUTHORIZED
194-
except InvalidInputsException as e:
195-
cache.setKey(
196-
message["id"],
197-
getErrorArtifact(message["id"], str(e), StatusCode.INVALID_INPUTS),
198-
)
199-
statusCode = StatusCode.INVALID_INPUTS
200-
except NoProcessingException:
216+
statusCode, response = self.run_resolver(
217+
self._resolvers[artifact["method"]],
218+
context,
219+
(message["id"], artifact["inputs"]),
220+
)
221+
if statusCode == StatusCode.NO_PROCESSING:
201222
return StatusCode.NO_PROCESSING
202-
except MethodNotFoundException as e:
203-
cache.setKey(
204-
message["id"],
205-
getErrorArtifact(
206-
message["id"], str(e), StatusCode.METHOD_NOT_FOUND
207-
),
208-
)
209-
statusCode = StatusCode.METHOD_NOT_FOUND
210-
except Exception as e:
211-
cache.setKey(
212-
message["id"],
213-
getErrorArtifact(message["id"], str(e), StatusCode.SERVER_ERROR),
214-
)
215-
statusCode = StatusCode.SERVER_ERROR
216-
finally:
217-
evaluate_post_hooks(bus, cache, message, artifact)
218-
return statusCode
223+
224+
cache.setKey(message["id"], response)
225+
evaluate_post_hooks(bus, cache, message, artifact)
226+
return statusCode
219227

220228
cache.setKey(
221229
message["id"],

servc/svc/config/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@
1818
"conf.bus.routemap": json.loads(os.getenv("CONF__BUS__ROUTEMAP", json.dumps({}))),
1919
"conf.bus.prefix": "",
2020
"conf.worker.bindtoeventexchange": True,
21+
"conf.worker.exiton5xx": True,
2122
}
2223

24+
BOOLEAN_CONFIGS = os.getenv(
25+
"SERVC_BOOLEAN_CONFIGS", "conf.worker.exiton5xx,conf.worker.bindtoeventexchange"
26+
).split(",")
2327
DOT_MARKER = os.getenv("SERVC_DOT_MARKER", "_DOT_")
2428
DASH_MARKER = os.getenv("SERVC_DASH_MARKER", "_DASH_")
2529

@@ -53,7 +57,10 @@ def __init__(self, config_path: str | None = None):
5357
"CONF__FILE",
5458
"CONF__BUS__ROUTEMAP",
5559
):
56-
self.setValue(key.replace(DASH_MARKER, "-").replace("__", "."), value)
60+
newkey = key.replace(DASH_MARKER, "-").replace("__", ".")
61+
if newkey.lower() in BOOLEAN_CONFIGS:
62+
value = value.lower() in ("yes", "true", "t", "1")
63+
self.setValue(newkey, value)
5764

5865
self.setValue("conf.bus.instanceid", self.get("conf.instanceid"))
5966

0 commit comments

Comments
 (0)