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.
Files changed (54) hide show
  1. {fixcore_engine-0.1.3/fixcore_engine.egg-info → fixcore_engine-0.1.5}/PKG-INFO +1 -1
  2. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/initiator.py +22 -10
  3. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5/fixcore_engine.egg-info}/PKG-INFO +1 -1
  4. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/pyproject.toml +1 -1
  5. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/LICENSE +0 -0
  6. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/README.md +0 -0
  7. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/__init__.py +0 -0
  8. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/application.py +0 -0
  9. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui.py +0 -0
  10. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/app.js +0 -0
  11. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/fixcore_logo.svg +0 -0
  12. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/index.html +0 -0
  13. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/gui_ui/style.css +0 -0
  14. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/__init__.py +0 -0
  15. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/base.py +0 -0
  16. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/factory.py +0 -0
  17. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/file_log.py +0 -0
  18. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/log/screen.py +0 -0
  19. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/__init__.py +0 -0
  20. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/cracker.py +0 -0
  21. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/data_dictionary.py +0 -0
  22. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/exceptions.py +0 -0
  23. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/field.py +0 -0
  24. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/message/message.py +0 -0
  25. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/__init__.py +0 -0
  26. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session.py +0 -0
  27. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session_id.py +0 -0
  28. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/session_settings.py +0 -0
  29. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/session/state.py +0 -0
  30. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/__init__.py +0 -0
  31. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/base.py +0 -0
  32. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/factory.py +0 -0
  33. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/file_store.py +0 -0
  34. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/store/memory.py +0 -0
  35. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/__init__.py +0 -0
  36. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/acceptor.py +0 -0
  37. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore/transport/framer.py +0 -0
  38. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/SOURCES.txt +0 -0
  39. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/dependency_links.txt +0 -0
  40. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/entry_points.txt +0 -0
  41. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/requires.txt +0 -0
  42. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/fixcore_engine.egg-info/top_level.txt +0 -0
  43. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/setup.cfg +0 -0
  44. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_cracker.py +0 -0
  45. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_data_dictionary.py +0 -0
  46. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_file_log.py +0 -0
  47. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_file_store.py +0 -0
  48. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_framer.py +0 -0
  49. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_integration.py +0 -0
  50. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_message.py +0 -0
  51. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_session.py +0 -0
  52. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_session_id.py +0 -0
  53. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_store.py +0 -0
  54. {fixcore_engine-0.1.3 → fixcore_engine-0.1.5}/tests/test_transport.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixcore-engine
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Pure Python FIX protocol engine
5
5
  Author-email: Aidan Chisholm <aidan.chisholm@gmail.com>
6
6
  License: MIT License
@@ -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
- # Connection refused or network error wait and retry
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 asyncio.wait_for(reader.read(4096), timeout=1.0)
129
- except asyncio.TimeoutError:
130
- continue
131
- except (ConnectionResetError, asyncio.IncompleteReadError):
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fixcore-engine
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Pure Python FIX protocol engine
5
5
  Author-email: Aidan Chisholm <aidan.chisholm@gmail.com>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fixcore-engine"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "Pure Python FIX protocol engine"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
File without changes
File without changes
File without changes