port-ocean 0.28.1__py3-none-any.whl → 0.28.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
1
  import datetime
2
2
  from typing import Any, Literal
3
+
3
4
  from port_ocean.clients.port.client import PortClient
5
+ from port_ocean.context.ocean import ocean
6
+ from port_ocean.helpers.metric.metric import MetricPhase, MetricType
4
7
  from port_ocean.utils.misc import IntegrationStateStatus
5
8
  from port_ocean.utils.time import get_next_occurrence
6
- from port_ocean.context.ocean import ocean
7
- from port_ocean.helpers.metric.metric import MetricType, MetricPhase
8
9
 
9
10
 
10
11
  class ResyncStateUpdater:
@@ -99,3 +100,4 @@ class ResyncStateUpdater:
99
100
  await ocean.metrics.report_sync_metrics(
100
101
  kinds=[ocean.metrics.current_resource_kind()]
101
102
  )
103
+ ocean.metrics.event_id = ""
@@ -1,9 +1,9 @@
1
- import sys
2
1
  import os
2
+ import sys
3
+ import uuid
3
4
  from logging import LogRecord
4
5
  from logging.handlers import QueueHandler, QueueListener
5
6
  from queue import Queue
6
- import uuid
7
7
 
8
8
  import loguru
9
9
  from loguru import logger
@@ -60,8 +60,10 @@ def _http_loguru_handler(level: LogLevelType) -> None:
60
60
  logger.configure(patcher=exception_deserializer)
61
61
 
62
62
  http_memory_handler = HTTPMemoryHandler()
63
- signal_handler.register(http_memory_handler.wait_for_lingering_threads)
64
- signal_handler.register(http_memory_handler.flush)
63
+ signal_handler.register(
64
+ http_memory_handler.wait_for_lingering_threads, priority=-200
65
+ )
66
+ signal_handler.register(http_memory_handler.flush, priority=-200)
65
67
 
66
68
  queue_listener = QueueListener(queue, http_memory_handler)
67
69
  queue_listener.start()
port_ocean/ocean.py CHANGED
@@ -97,6 +97,22 @@ class Ocean:
97
97
  )
98
98
  self.app_initialized = False
99
99
 
100
+ signal_handler.register(self._report_resync_aborted)
101
+
102
+ async def _report_resync_aborted(self) -> None:
103
+ """
104
+ Report resync status as aborted when the app receives a kill signal.
105
+ This ensures Port is notified that the integration was interrupted.
106
+ """
107
+ try:
108
+ if self.metrics.event_id != "":
109
+ await self.resync_state_updater.update_after_resync(
110
+ IntegrationStateStatus.Aborted
111
+ )
112
+ logger.info("Resync status reported as aborted due to app shutdown")
113
+ except Exception as e:
114
+ logger.warning(f"Failed to report resync status on shutdown: {e}")
115
+
100
116
  def _get_process_execution_mode(self) -> ProcessExecutionMode:
101
117
  if self.config.process_execution_mode:
102
118
  return self.config.process_execution_mode
port_ocean/utils/misc.py CHANGED
@@ -1,11 +1,12 @@
1
- from enum import Enum
2
1
  import inspect
3
- from importlib.util import spec_from_file_location, module_from_spec
2
+ from enum import Enum
3
+ from importlib.util import module_from_spec, spec_from_file_location
4
4
  from pathlib import Path
5
5
  from time import time
6
6
  from types import ModuleType
7
- from typing import Callable, Any
7
+ from typing import Any, Callable
8
8
  from uuid import uuid4
9
+
9
10
  import tomli
10
11
  import yaml
11
12
 
@@ -14,6 +15,7 @@ class IntegrationStateStatus(Enum):
14
15
  Running = "running"
15
16
  Failed = "failed"
16
17
  Completed = "completed"
18
+ Aborted = "aborted"
17
19
 
18
20
 
19
21
  def get_time(seconds_precision: bool = True) -> float:
@@ -1,37 +1,52 @@
1
1
  from asyncio import iscoroutinefunction
2
- from typing import Callable, Any
2
+ from typing import Any, Callable
3
3
 
4
4
  from werkzeug.local import LocalProxy, LocalStack
5
5
 
6
6
  from port_ocean.exceptions.utils import (
7
- SignalHandlerNotInitialized,
8
7
  SignalHandlerAlreadyInitialized,
8
+ SignalHandlerNotInitialized,
9
9
  )
10
10
  from port_ocean.utils.misc import generate_uuid
11
11
 
12
12
 
13
13
  class SignalHandler:
14
14
  def __init__(self) -> None:
15
- self._handlers: dict[str, Callable[[], Any]] = {}
15
+ self._handlers: dict[str, tuple[Callable[[], Any], int]] = {}
16
16
 
17
17
  async def exit(self) -> None:
18
18
  """
19
19
  Handles the exit signal.
20
+ Executes handlers in priority order (highest priority first).
20
21
  """
21
- while self._handlers:
22
- _, handler = self._handlers.popitem()
22
+ # Sort handlers by priority (highest first) and execute them
23
+ sorted_handlers = sorted(
24
+ self._handlers.items(), key=lambda x: x[1][1], reverse=True
25
+ )
26
+
27
+ for _id, (handler, _) in sorted_handlers:
23
28
  if iscoroutinefunction(handler):
24
29
  await handler()
25
30
  else:
26
31
  handler()
27
32
 
28
- def register(self, callback: Callable[[], Any]) -> str:
29
- _id = generate_uuid()
30
- self._handlers[_id] = callback
33
+ def register(self, callback: Callable[[], Any], priority: int = 0) -> str:
34
+ """
35
+ Register a callback with a priority.
36
+
37
+ Args:
38
+ callback: The callback function to register
39
+ priority: Priority level (higher numbers execute first, default: 0)
31
40
 
41
+ Returns:
42
+ Unique identifier for the registered callback
43
+ """
44
+ _id = generate_uuid()
45
+ self._handlers[_id] = (callback, priority)
32
46
  return _id
33
47
 
34
48
  def unregister(self, _id: str) -> None:
49
+ """Unregister a callback by its ID."""
35
50
  del self._handlers[_id]
36
51
 
37
52
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.28.1
3
+ Version: 0.28.2
4
4
  Summary: Port Ocean is a CLI tool for managing your Port projects.
5
5
  Home-page: https://app.getport.io
6
6
  Keywords: ocean,port-ocean,port
@@ -111,7 +111,7 @@ port_ocean/core/handlers/queue/abstract_queue.py,sha256=SaivrYbqg8qsX6wtQlJZyxgc
111
111
  port_ocean/core/handlers/queue/group_queue.py,sha256=JvvJOwz9z_aI4CjPr7yQX-0rOgqLI5wMdxWk2x5x-34,4989
112
112
  port_ocean/core/handlers/queue/local_queue.py,sha256=Y6qabDbrQ8aOPTN6Ct3lnMU7JnT8O8iTpoxMoVt6lFs,643
113
113
  port_ocean/core/handlers/resync_state_updater/__init__.py,sha256=kG6y-JQGpPfuTHh912L_bctIDCzAK4DN-d00S7rguWU,81
114
- port_ocean/core/handlers/resync_state_updater/updater.py,sha256=R7K0n-MljKtOFEh2XZKi_fBUOWIdt4X6IZIw-2WMtv0,3813
114
+ port_ocean/core/handlers/resync_state_updater/updater.py,sha256=9nv7KY9ueszdGpZKss25foyQ_GYYzpuVZyusEaMNjKU,3850
115
115
  port_ocean/core/handlers/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
116
  port_ocean/core/handlers/webhook/abstract_webhook_processor.py,sha256=5KwZkdkDd5HdVkXPzKiqabodZKl-hOtMypkTKd8Hq3M,3891
117
117
  port_ocean/core/handlers/webhook/processor_manager.py,sha256=0KRPD1ae-7w0na2AZY-rq9_gY0IaMv9LdwEh6y4_OiQ,13282
@@ -147,10 +147,10 @@ port_ocean/helpers/retry.py,sha256=QM04mzaevIUlg8HnHjeY9UT_D4k26BHx3hVkCjV_jnY,2
147
147
  port_ocean/helpers/stream.py,sha256=_UwsThzXynxWzL8OlBT1pmb2evZBi9HaaqeAGNuTuOI,2338
148
148
  port_ocean/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
149
  port_ocean/log/handlers.py,sha256=LJ1WAfq7wYCrBpeLPihMKmWjdSahKKXNHFMRYkbk0Co,3630
150
- port_ocean/log/logger_setup.py,sha256=0K3zVG0YYrYOWEV8-rCGks1o-bMRxgHXlqawu9w_tSw,2656
150
+ port_ocean/log/logger_setup.py,sha256=5JxGlg7TKDbYD2ladgaHufCv6PTJXvdQJ8l6cP3MKFA,2700
151
151
  port_ocean/log/sensetive.py,sha256=lVKiZH6b7TkrZAMmhEJRhcl67HNM94e56x12DwFgCQk,2920
152
152
  port_ocean/middlewares.py,sha256=9wYCdyzRZGK1vjEJ28FY_DkfwDNENmXp504UKPf5NaQ,2727
153
- port_ocean/ocean.py,sha256=IhsLnPqEJ2SflnBAt-byxGl9w_ULkdvd6-sxBbVQtJw,8874
153
+ port_ocean/ocean.py,sha256=erUfBUJLsHs9uAaoHY-cPczqbICG4Gu02luK0nfoJAQ,9556
154
154
  port_ocean/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
155
  port_ocean/run.py,sha256=CmKz14bxfdOooNbQ5QqH1MwX-XLYVG4NgT4KbrzFaqI,2216
156
156
  port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
@@ -202,14 +202,14 @@ port_ocean/utils/async_http.py,sha256=aDsw3gQIMwt6qLegbZtkHqD8em48tKvbITnblsrTY3
202
202
  port_ocean/utils/async_iterators.py,sha256=CPXskYWkhkZtAG-ducEwM8537t3z5usPEqXR9vcivzw,3715
203
203
  port_ocean/utils/cache.py,sha256=tRwPomG2VIxx8ZNi4QYH6Yc47d9yYV1A7Hx-L_fX4Dg,4494
204
204
  port_ocean/utils/ipc.py,sha256=eTjTTvsKl6IXYeOkIjP5iyrw-8gLQ9rf15WeyxCqXog,912
205
- port_ocean/utils/misc.py,sha256=0q2cJ5psqxn_5u_56pT7vOVQ3shDM02iC1lzyWQ_zl0,2098
205
+ port_ocean/utils/misc.py,sha256=cQGBWL9IN7ER6s7xyHzeKvj60ntW70WiYIq9MyLe1nY,2123
206
206
  port_ocean/utils/queue_utils.py,sha256=KWWl8YVnG-glcfIHhM6nefY-2sou_C6DVP1VynQwzB4,2762
207
207
  port_ocean/utils/repeat.py,sha256=U2OeCkHPWXmRTVoPV-VcJRlQhcYqPWI5NfmPlb1JIbc,3229
208
- port_ocean/utils/signal.py,sha256=mMVq-1Ab5YpNiqN4PkiyTGlV_G0wkUDMMjTZp5z3pb0,1514
208
+ port_ocean/utils/signal.py,sha256=J1sI-e_32VHP_VUa5bskLMFoJjJOAk5isrnewKDikUI,2125
209
209
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
210
210
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
211
- port_ocean-0.28.1.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
212
- port_ocean-0.28.1.dist-info/METADATA,sha256=PSPEzll-3f7zXAELk1jUxqAlzwsxtxLksle9ITyREwg,7015
213
- port_ocean-0.28.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
214
- port_ocean-0.28.1.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
215
- port_ocean-0.28.1.dist-info/RECORD,,
211
+ port_ocean-0.28.2.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
212
+ port_ocean-0.28.2.dist-info/METADATA,sha256=5T2f0NQsbLtV8Ero37oN7KmSDdG6VY5YbgjCX1S64fo,7015
213
+ port_ocean-0.28.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
214
+ port_ocean-0.28.2.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
215
+ port_ocean-0.28.2.dist-info/RECORD,,