fixcore-engine 0.1.3__tar.gz → 0.1.5__tar.gz
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.
- {fixcore_engine-0.1.3/fixcore_engine.egg-info → fixcore_engine-0.1.5}/PKG-INFO +1 -1
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/initiator.py +22 -10
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5/fixcore_engine.egg-info}/PKG-INFO +1 -1
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/pyproject.toml +1 -1
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/LICENSE +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/README.md +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/application.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/app.js +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/fixcore_logo.svg +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/index.html +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/style.css +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/base.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/factory.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/file_log.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/screen.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/cracker.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/data_dictionary.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/exceptions.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/field.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/message.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session_id.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session_settings.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/state.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/base.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/factory.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/file_store.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/memory.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/__init__.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/acceptor.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/framer.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/SOURCES.txt +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/dependency_links.txt +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/entry_points.txt +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/requires.txt +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/top_level.txt +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/setup.cfg +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_cracker.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_data_dictionary.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_file_log.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_file_store.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_framer.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_integration.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_message.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_session.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_session_id.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_store.py +0 -0
- {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_transport.py +0 -0
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import logging
|
|
6
7
|
|
|
7
8
|
from fixcore.application import Application
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
8
11
|
from fixcore.log.base import LogFactory
|
|
9
12
|
from fixcore.session.session import Session
|
|
10
13
|
from fixcore.session.session_id import SessionID
|
|
@@ -61,16 +64,20 @@ class SocketInitiator:
|
|
|
61
64
|
"""Launch a connect-loop task for each configured initiator session."""
|
|
62
65
|
self._stop_event.clear()
|
|
63
66
|
self._no_reconnect.clear()
|
|
67
|
+
logger.info("SocketInitiator starting %d session(s)", len(self._sessions))
|
|
64
68
|
for sid, session in self._sessions.items():
|
|
65
69
|
task = asyncio.create_task(
|
|
66
70
|
self._connect_loop(sid, session),
|
|
67
71
|
name=f"initiator-{sid}",
|
|
68
72
|
)
|
|
69
73
|
self._tasks.append(task)
|
|
74
|
+
logger.debug("Connect-loop task created for %s", sid)
|
|
70
75
|
|
|
71
76
|
async def stop(self) -> None:
|
|
72
77
|
"""Signal all connect loops to exit and wait for them to finish."""
|
|
73
78
|
self._stop_event.set()
|
|
79
|
+
for task in self._tasks:
|
|
80
|
+
task.cancel()
|
|
74
81
|
if self._tasks:
|
|
75
82
|
await asyncio.gather(*self._tasks, return_exceptions=True)
|
|
76
83
|
self._tasks.clear()
|
|
@@ -106,14 +113,17 @@ class SocketInitiator:
|
|
|
106
113
|
port = int(self._settings.get(sid, "SocketConnectPort"))
|
|
107
114
|
reconnect = self._settings.get_int(sid, "ReconnectInterval", 10)
|
|
108
115
|
|
|
116
|
+
logger.info("[%s] Connect loop started — target %s:%s", sid, host, port)
|
|
109
117
|
while not self._stop_event.is_set():
|
|
118
|
+
logger.debug("[%s] Attempting connection to %s:%s", sid, host, port)
|
|
110
119
|
try:
|
|
111
120
|
reader, writer = await asyncio.open_connection(host, port)
|
|
112
|
-
except OSError:
|
|
113
|
-
|
|
121
|
+
except OSError as exc:
|
|
122
|
+
logger.warning("[%s] Connection failed: %s — retrying in %ss", sid, exc, reconnect)
|
|
114
123
|
await self._interruptible_sleep(reconnect)
|
|
115
124
|
continue
|
|
116
125
|
|
|
126
|
+
logger.info("[%s] TCP connected to %s:%s", sid, host, port)
|
|
117
127
|
framer = MessageFramer()
|
|
118
128
|
|
|
119
129
|
async def send_fn(data: bytes, _w: asyncio.StreamWriter = writer) -> None:
|
|
@@ -121,22 +131,26 @@ class SocketInitiator:
|
|
|
121
131
|
await _w.drain()
|
|
122
132
|
|
|
123
133
|
await session.on_connect(send_fn)
|
|
134
|
+
logger.debug("[%s] on_connect complete — Logon sent", sid)
|
|
124
135
|
|
|
125
136
|
try:
|
|
126
137
|
while not self._stop_event.is_set():
|
|
127
138
|
try:
|
|
128
|
-
data = await
|
|
129
|
-
except asyncio.
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
data = await reader.read(4096)
|
|
140
|
+
except (ConnectionResetError, asyncio.IncompleteReadError,
|
|
141
|
+
asyncio.CancelledError) as exc:
|
|
142
|
+
logger.info("[%s] Read interrupted: %s", sid, type(exc).__name__)
|
|
132
143
|
break
|
|
133
144
|
if not data:
|
|
145
|
+
logger.info("[%s] Connection closed by peer", sid)
|
|
134
146
|
break
|
|
135
147
|
|
|
148
|
+
logger.debug("[%s] Received %d bytes", sid, len(data))
|
|
136
149
|
for raw_msg in framer.feed(data):
|
|
137
150
|
await session.on_data(raw_msg)
|
|
138
151
|
|
|
139
152
|
finally:
|
|
153
|
+
logger.info("[%s] Disconnecting", sid)
|
|
140
154
|
await session.on_disconnect()
|
|
141
155
|
try:
|
|
142
156
|
writer.close()
|
|
@@ -146,14 +160,12 @@ class SocketInitiator:
|
|
|
146
160
|
framer.reset()
|
|
147
161
|
|
|
148
162
|
if not self._stop_event.is_set() and not self._no_reconnect.is_set():
|
|
163
|
+
logger.info("[%s] Waiting %ss before reconnect", sid, reconnect)
|
|
149
164
|
await self._interruptible_sleep(reconnect)
|
|
150
165
|
|
|
151
166
|
async def _interruptible_sleep(self, seconds: float) -> None:
|
|
152
167
|
"""Sleep for *seconds* but wake immediately if stop is requested."""
|
|
153
168
|
try:
|
|
154
|
-
await asyncio.wait_for(
|
|
155
|
-
asyncio.shield(self._stop_event.wait()),
|
|
156
|
-
timeout=seconds,
|
|
157
|
-
)
|
|
169
|
+
await asyncio.wait_for(self._stop_event.wait(), timeout=seconds)
|
|
158
170
|
except asyncio.TimeoutError:
|
|
159
171
|
pass
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|