simo 3.1.4__py3-none-any.whl → 3.1.5__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.

Potentially problematic release.


This version of simo might be problematic. Click here for more details.

@@ -1,19 +1,73 @@
1
1
  from django.contrib.gis.db.backends.postgis.base import (
2
2
  DatabaseWrapper as PostGisPsycopg2DatabaseWrapper
3
3
  )
4
- from django.db.utils import OperationalError, InterfaceError
4
+ """Custom PostGIS database wrapper with light self-healing.
5
+
6
+ We retry cursor creation on transient driver-level errors. Previously we
7
+ were catching Django's wrapper exceptions (django.db.utils.InterfaceError/
8
+ OperationalError). However, those are only raised by the outer
9
+ `wrap_database_errors` context. Inside `create_cursor()` the driver
10
+ (`psycopg2`) raises its own exceptions, so our except block never ran and
11
+ connections weren't healed.
12
+
13
+ By catching psycopg2 errors here (in addition to Django's), we ensure
14
+ we can close() and reconnect() this connection when `self.connection`
15
+ is already closed or becomes unusable, avoiding busy error loops in
16
+ MQTT threads and periodic tasks.
17
+ """
18
+
19
+ from django.db.utils import OperationalError as DjangoOperationalError, InterfaceError as DjangoInterfaceError
20
+ try:
21
+ # Catch driver-level errors where they originate.
22
+ from psycopg2 import OperationalError as PsycopgOperationalError, InterfaceError as PsycopgInterfaceError
23
+ except Exception: # pragma: no cover - very defensive
24
+ PsycopgOperationalError = PsycopgInterfaceError = Exception
5
25
  from django.utils.asyncio import async_unsafe
26
+ import time
27
+ import random
6
28
 
7
29
 
8
30
  class DatabaseWrapper(PostGisPsycopg2DatabaseWrapper):
9
31
  @async_unsafe
10
32
  def create_cursor(self, name=None):
33
+ """Create a DB cursor with a single, simple heal-once path.
34
+
35
+ - Fast path: return cursor immediately.
36
+ - On error: if it's a connectivity issue (known exceptions or
37
+ connection.closed set), close + backoff + reconnect, then retry once.
38
+ - Otherwise: re-raise the original exception.
39
+ """
11
40
  try:
12
41
  return super().create_cursor(name=name)
13
- except (InterfaceError, OperationalError):
14
- # Heal this very connection
15
- self.close()
16
- self.connect()
17
- return super().create_cursor(name=name)
42
+ except Exception as e:
43
+ # Determine if this is a connectivity problem
44
+ is_connectivity_err = isinstance(
45
+ e,
46
+ (
47
+ DjangoInterfaceError,
48
+ DjangoOperationalError,
49
+ PsycopgInterfaceError,
50
+ PsycopgOperationalError,
51
+ ),
52
+ )
53
+ if not is_connectivity_err:
54
+ try:
55
+ conn = getattr(self, 'connection', None)
56
+ is_connectivity_err = bool(getattr(conn, 'closed', 0))
57
+ except Exception:
58
+ is_connectivity_err = False
18
59
 
60
+ if not is_connectivity_err:
61
+ # Not a connection issue; bubble up unchanged
62
+ raise
19
63
 
64
+ # Heal this very connection and retry once
65
+ try:
66
+ self.close()
67
+ finally:
68
+ try:
69
+ time.sleep(0.05 + random.random() * 0.15) # 50–200 ms
70
+ except Exception:
71
+ pass
72
+ self.connect()
73
+ return super().create_cursor(name=name)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simo
3
- Version: 3.1.4
3
+ Version: 3.1.5
4
4
  Summary: Smart Home Supremacy
5
5
  Author-email: "Simon V." <simon@simo.io>
6
6
  Project-URL: Homepage, https://simo.io
@@ -191,7 +191,7 @@ simo/core/__pycache__/views.cpython-38.pyc,sha256=kYKvEcyKicdkTcN0iEJ4pT101-KHiZ
191
191
  simo/core/__pycache__/widgets.cpython-312.pyc,sha256=f_AiYFfA7Wl4Wm9FqUOlluSGLAN_nkLyDUsKpkScsXg,4447
192
192
  simo/core/__pycache__/widgets.cpython-38.pyc,sha256=sR0ZeHCHrhnNDBJuRrxp3zUsfBp0xrtF0xrK2TkQv1o,3520
193
193
  simo/core/db_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
194
- simo/core/db_backend/base.py,sha256=4vl0Nx8PcBG5C8QQpAQPFu-TKH8Hs6R5OmzJqIiLibQ,598
194
+ simo/core/db_backend/base.py,sha256=fGagw119bvP3Ns3NFvIDlrlNSa9-LLt2HMuIjnB9h9g,2933
195
195
  simo/core/db_backend/__pycache__/__init__.cpython-312.pyc,sha256=Brq4UBCggJrt590OFV3VmgARJYRK902FnnFFFK_Azng,133
196
196
  simo/core/db_backend/__pycache__/__init__.cpython-38.pyc,sha256=sxC6PmFqnwe6RRKzSR7QtUFzRc_aRRR1fffsR3TPLRc,169
197
197
  simo/core/db_backend/__pycache__/base.cpython-312.pyc,sha256=ykKrTOC28v2cl0C--bqeLEaydHS5CG1RFGL0lon53HU,1135
@@ -11034,9 +11034,9 @@ simo/users/templates/invitations/expired_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCe
11034
11034
  simo/users/templates/invitations/expired_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11035
11035
  simo/users/templates/invitations/taken_msg.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11036
11036
  simo/users/templates/invitations/taken_suggestion.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11037
- simo-3.1.4.dist-info/licenses/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
11038
- simo-3.1.4.dist-info/METADATA,sha256=fdQuK5JIjFNaNn7FMY7R2vbKhlMuFf282kuWRWawPhc,2224
11039
- simo-3.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11040
- simo-3.1.4.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
11041
- simo-3.1.4.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
11042
- simo-3.1.4.dist-info/RECORD,,
11037
+ simo-3.1.5.dist-info/licenses/LICENSE.md,sha256=M7wm1EmMGDtwPRdg7kW4d00h1uAXjKOT3HFScYQMeiE,34916
11038
+ simo-3.1.5.dist-info/METADATA,sha256=hXkJ2qxHLFHebhXd3yRy4Gvj2Bd4Vi2-ulumfeyYcIM,2224
11039
+ simo-3.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11040
+ simo-3.1.5.dist-info/entry_points.txt,sha256=S9PwnUYmTSW7681GKDCxUbL0leRJIaRk6fDQIKgbZBA,135
11041
+ simo-3.1.5.dist-info/top_level.txt,sha256=GmS1hrAbpVqn9OWZh6UX82eIOdRLgYA82RG9fe8v4Rs,5
11042
+ simo-3.1.5.dist-info/RECORD,,
File without changes