Skip to content

Commit 89fdfd3

Browse files
authored
feat: add abandoned_time_limit to PublisherStalledCheck (#74)
* add new abandoned_time_limit config to PublisherStalledCheck * bump * fix
1 parent 9bdb36e commit 89fdfd3

File tree

6 files changed

+24
-18
lines changed

6 files changed

+24
-18
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ignore_missing_imports = true
44

55
[tool.poetry]
66
name = "pyth-observer"
7-
version = "0.2.9"
7+
version = "0.2.10"
88
description = "Alerts and stuff"
99
authors = []
1010
readme = "README.md"

pyth_observer/check/publisher.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ def error_message(self) -> dict:
221221
"symbol": self.__state.symbol,
222222
"publisher_price": f"{self.__state.price} ± {self.__state.confidence_interval}",
223223
"aggregate_price": f"{self.__state.price_aggregate} ± {self.__state.confidence_interval_aggregate}",
224-
"deviation": deviation,
224+
"deviation": f"{deviation:.2f}%",
225225
}
226226

227227
# Returns the distance between the aggregate price and the closest side of the publisher's confidence interval
@@ -237,6 +237,7 @@ def __init__(self, state: PublisherState, config: PublisherCheckConfig):
237237
self.__stall_time_limit: int = int(
238238
config["stall_time_limit"]
239239
) # Time in seconds
240+
self.__abandoned_time_limit: int = int(config["abandoned_time_limit"])
240241
self.__max_slot_distance: int = int(config["max_slot_distance"])
241242

242243
def state(self) -> PublisherState:
@@ -258,7 +259,7 @@ def run(self) -> bool:
258259
return True
259260

260261
publisher_key = (self.__state.publisher_name, self.__state.symbol)
261-
current_time = time.time()
262+
current_time = int(time.time())
262263
previous_price, last_change_time = PUBLISHER_CACHE.get(
263264
publisher_key, (None, None)
264265
)
@@ -267,7 +268,10 @@ def run(self) -> bool:
267268
PUBLISHER_CACHE[publisher_key] = (self.__state.price, current_time)
268269
return True
269270

270-
if (current_time - last_change_time) > self.__stall_time_limit:
271+
time_since_last_change = current_time - last_change_time
272+
if time_since_last_change > self.__stall_time_limit:
273+
if time_since_last_change > self.__abandoned_time_limit:
274+
return True # Abandon this check after the abandoned time limit
271275
return False
272276

273277
return True
@@ -279,8 +283,7 @@ def error_message(self) -> dict:
279283
"publisher": self.__state.publisher_name,
280284
"symbol": self.__state.symbol,
281285
"price": self.__state.price,
282-
"stall_duration": time.time()
283-
- PUBLISHER_CACHE[(self.__state.publisher_name, self.__state.symbol)][1],
286+
"stall_duration": f"{int(time.time()) - PUBLISHER_CACHE[(self.__state.publisher_name, self.__state.symbol)][1]} seconds",
284287
}
285288

286289

pyth_observer/dispatch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ async def run(self, states: List[State]):
9797
sent_events.append(event.send())
9898

9999
await asyncio.gather(*sent_events)
100-
await self.process_zenduty_events(current_time)
100+
if "ZendutyEvent" in self.config["events"]:
101+
await self.process_zenduty_events(current_time)
101102

102103
def check_price_feed(self, state: PriceFeedState) -> List[Check]:
103104
failed_checks: List[Check] = []

pyth_observer/event.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,8 @@ async def send(self):
132132

133133
formatted_message = ""
134134
for key, value in text.items():
135-
value_str = f"{value:.2f}%" if key == "deviation" else f"{value}"
136135
formatted_message += (
137-
f"*{key.capitalize().replace('_', ' ')}:* {value_str}\n"
136+
f"*{key.capitalize().replace('_', ' ')}:* {value}\n"
138137
)
139138

140139
message_data = {

sample.config.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ events:
1010
# NOTE: Uncomment to enable Datadog metrics, see README.md for datadog credential docs.
1111
# - DatadogEvent
1212
- LogEvent
13-
- TelegramEvent
13+
# - TelegramEvent
1414
checks:
1515
global:
1616
# Price feed checks
@@ -45,8 +45,9 @@ checks:
4545
max_slot_distance: 25
4646
max_aggregate_distance: 6
4747
PublisherStalledCheck:
48-
enable: true
49-
stall_time_limit: 60
48+
enable: false
49+
stall_time_limit: 30
50+
abandoned_time_limit: 600
5051
max_slot_distance: 25
5152
# Per-symbol config
5253
Crypto.MNGO/USD:
@@ -57,4 +58,5 @@ checks:
5758
max_slot_distance: 10000
5859
Crypto.BTC/USD:
5960
PublisherStalledCheck:
60-
stall_time_limit: 10 # This will override the global stall_time_limit for Crypto.BTC/USD
61+
enable: true
62+
stall_time_limit: 60

tests/test_checks_publisher.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,12 @@ def simulate_time_pass(seconds):
6363
current_time += seconds
6464
return current_time
6565

66-
def setup_check(state, stall_time_limit, max_slot_distance):
66+
def setup_check(state, stall_time_limit, abandoned_time_limit, max_slot_distance):
6767
check = PublisherStalledCheck(
6868
state,
6969
{
7070
"stall_time_limit": stall_time_limit,
71+
"abandoned_time_limit": abandoned_time_limit,
7172
"max_slot_distance": max_slot_distance,
7273
},
7374
)
@@ -83,17 +84,17 @@ def run_check(check, seconds, expected):
8384

8485
PUBLISHER_CACHE.clear()
8586
state_a = make_state(1, 100.0, 2.0, 1, 100.0, 1.0)
86-
check_a = setup_check(state_a, 5, 25)
87+
check_a = setup_check(state_a, 5, 25, 25)
8788
run_check(check_a, 5, True) # Should pass as it hits the limit exactly
8889

8990
PUBLISHER_CACHE.clear()
9091
state_b = make_state(1, 100.0, 2.0, 1, 100.0, 1.0)
91-
check_b = setup_check(state_b, 5, 25)
92+
check_b = setup_check(state_b, 5, 25, 25)
9293
run_check(check_b, 6, False) # Should fail as it exceeds the limit
9394

9495
PUBLISHER_CACHE.clear()
9596
state_c = make_state(1, 100.0, 2.0, 1, 100.0, 1.0)
96-
check_c = setup_check(state_c, 5, 25)
97+
check_c = setup_check(state_c, 5, 25, 25)
9798
run_check(check_c, 2, True) # Initial check should pass
9899
state_c.price = 105.0 # Change the price
99100
run_check(check_c, 3, True) # Should pass as price changes
@@ -108,5 +109,5 @@ def run_check(check, seconds, expected):
108109
state_d = make_state(1, 100.0, 2.0, 1, 100.0, 1.0)
109110
state_d.latest_block_slot = 25
110111
state_d.slot = 0
111-
check_d = setup_check(state_d, 5, 25)
112+
check_d = setup_check(state_d, 5, 25, 25)
112113
run_check(check_d, 10, True) # Should pass as the publisher is offline

0 commit comments

Comments
 (0)