mercuto-client 0.3.0__py3-none-any.whl → 0.3.1__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 mercuto-client might be problematic. Click here for more details.
- mercuto_client/_tests/test_ingester/test_file_processor.py +1 -1
- mercuto_client/ingester/__main__.py +5 -2
- mercuto_client/ingester/processor.py +14 -12
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.1.dist-info}/METADATA +1 -1
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.1.dist-info}/RECORD +8 -8
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.1.dist-info}/WHEEL +0 -0
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {mercuto_client-0.3.0.dist-info → mercuto_client-0.3.1.dist-info}/top_level.txt +0 -0
|
@@ -37,7 +37,7 @@ def temp_env() -> Generator[Tuple[FileProcessor, str, str], None, None]:
|
|
|
37
37
|
|
|
38
38
|
def test_init_db(temp_env: Tuple[FileProcessor, str, str]) -> None:
|
|
39
39
|
"""Verify database initialization"""
|
|
40
|
-
|
|
40
|
+
_, _, db_path = temp_env
|
|
41
41
|
conn: sqlite3.Connection = sqlite3.connect(db_path)
|
|
42
42
|
cursor: sqlite3.Cursor = conn.cursor()
|
|
43
43
|
cursor.execute(
|
|
@@ -43,6 +43,8 @@ if __name__ == '__main__':
|
|
|
43
43
|
parser.add_argument('-s', '--size', type=int,
|
|
44
44
|
help='Size in MB for total amount of files to store in the buffer. \
|
|
45
45
|
Default is 75% of the available disk space on the buffer partition excluding the directory itself', default=None)
|
|
46
|
+
parser.add_argument('--max-files', type=int,
|
|
47
|
+
help='Maximum number of files to keep in the buffer. Default is to use the size param.', default=None)
|
|
46
48
|
parser.add_argument('--max-attempts', type=int,
|
|
47
49
|
help='Maximum number of attempts to process a file before giving up. Default is 1000.',
|
|
48
50
|
default=1000)
|
|
@@ -114,7 +116,7 @@ if __name__ == '__main__':
|
|
|
114
116
|
os.makedirs(ftp_dir, exist_ok=True)
|
|
115
117
|
|
|
116
118
|
size = args.size
|
|
117
|
-
if size is None:
|
|
119
|
+
if size is None and args.max_files is None:
|
|
118
120
|
size = get_free_space_excluding_files(buffer_directory) * 0.75 // (1024 * 1024) # Convert to MB
|
|
119
121
|
logging.info(f"Buffer size set to {size} MB based on available disk space.")
|
|
120
122
|
|
|
@@ -146,7 +148,8 @@ if __name__ == '__main__':
|
|
|
146
148
|
db_path=database_path,
|
|
147
149
|
process_callback=ingester.process_file,
|
|
148
150
|
max_attempts=args.max_attempts,
|
|
149
|
-
free_space_mb=size
|
|
151
|
+
free_space_mb=size,
|
|
152
|
+
max_files=args.max_files)
|
|
150
153
|
|
|
151
154
|
processor.scan_existing_files()
|
|
152
155
|
|
|
@@ -8,6 +8,16 @@ from typing import Callable, Optional
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
def _default_standard_clock(_: str):
|
|
12
|
+
# Default clock function to get current time in seconds since epoch
|
|
13
|
+
return datetime.now(timezone.utc).timestamp()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _default_file_clock(filepath: str) -> float:
|
|
17
|
+
# Default clock function to get file creation time in seconds since epoch
|
|
18
|
+
return os.path.getctime(filepath)
|
|
19
|
+
|
|
20
|
+
|
|
11
21
|
class FileProcessor:
|
|
12
22
|
"""
|
|
13
23
|
System for processing files in a strict order with retry logic.
|
|
@@ -59,11 +69,7 @@ class FileProcessor:
|
|
|
59
69
|
self._max_attempts = max_attempts
|
|
60
70
|
self._process_callback = process_callback
|
|
61
71
|
self._free_space_mb = free_space_mb
|
|
62
|
-
if clock is None
|
|
63
|
-
# Default clock function to get current time in seconds since epoch
|
|
64
|
-
def clock(_): return datetime.now(timezone.utc).timestamp()
|
|
65
|
-
self._clock = clock
|
|
66
|
-
|
|
72
|
+
self._clock = clock if clock is not None else _default_standard_clock
|
|
67
73
|
os.makedirs(self._buffer_dir, exist_ok=True)
|
|
68
74
|
self._init_db()
|
|
69
75
|
|
|
@@ -102,9 +108,7 @@ class FileProcessor:
|
|
|
102
108
|
|
|
103
109
|
"""
|
|
104
110
|
if clock is None:
|
|
105
|
-
|
|
106
|
-
def clock(filepath: str) -> float:
|
|
107
|
-
return os.path.getctime(filepath)
|
|
111
|
+
clock = _default_file_clock
|
|
108
112
|
|
|
109
113
|
conn = sqlite3.connect(self._db_path)
|
|
110
114
|
cursor = conn.cursor()
|
|
@@ -241,7 +245,7 @@ class FileProcessor:
|
|
|
241
245
|
|
|
242
246
|
def free_space_mb() -> float:
|
|
243
247
|
"""Returns the free space in MB on the partition where the buffer directory is located."""
|
|
244
|
-
|
|
248
|
+
_, _, free = shutil.disk_usage(self._buffer_dir)
|
|
245
249
|
return free / (1024 * 1024)
|
|
246
250
|
|
|
247
251
|
while free_space_mb() < self._free_space_mb:
|
|
@@ -261,19 +265,17 @@ class FileProcessor:
|
|
|
261
265
|
return False
|
|
262
266
|
|
|
263
267
|
filepath = oldest_file[0]
|
|
264
|
-
removed = False
|
|
265
268
|
if os.path.exists(filepath):
|
|
266
269
|
os.remove(filepath)
|
|
267
270
|
cursor.execute(
|
|
268
271
|
"DELETE FROM file_buffer WHERE filepath = ?", (filepath,))
|
|
269
272
|
conn.commit()
|
|
270
|
-
removed = True
|
|
271
273
|
logger.info(f"Deleted oldest file {filepath}")
|
|
272
274
|
else:
|
|
273
275
|
logger.warning(f"Oldest file {filepath} does not exist.")
|
|
274
276
|
|
|
275
277
|
conn.close()
|
|
276
|
-
return
|
|
278
|
+
return True
|
|
277
279
|
|
|
278
280
|
def add_file_to_db(self, filepath: str) -> None:
|
|
279
281
|
"""Adds a new file to database and triggers processing."""
|
|
@@ -8,17 +8,17 @@ mercuto_client/util.py,sha256=PWNp8BU9wa_sKMPxW0R1yveEF1XslZXG8sw6BZvUoO8,2603
|
|
|
8
8
|
mercuto_client/_tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
mercuto_client/_tests/conftest.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
10
|
mercuto_client/_tests/test_ingester/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
-
mercuto_client/_tests/test_ingester/test_file_processor.py,sha256=
|
|
11
|
+
mercuto_client/_tests/test_ingester/test_file_processor.py,sha256=J-fscfEcnXdWAthmHzPbjBPB3BwsRcX-ZB7yaoX56lo,7391
|
|
12
12
|
mercuto_client/_tests/test_ingester/test_ftp.py,sha256=w1CHAGcZy88D2-nY61Gj16l1nHcer9LIKaMc_DXk23o,1318
|
|
13
13
|
mercuto_client/_tests/test_ingester/test_parsers.py,sha256=R9GnzAaGu_tva0s23VpwEVfEsEUcto3kN3EloIxZvVY,5917
|
|
14
14
|
mercuto_client/_tests/test_mocking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
mercuto_client/_tests/test_mocking/conftest.py,sha256=M-HikiSj_uuYAEYQnFA0uDtSBpZjO2YXjzxNbluQdMQ,266
|
|
16
16
|
mercuto_client/_tests/test_mocking/test_mock_identity.py,sha256=394r6A_xK78tse4CZA345JpIlIKF_GnPz2xXEjc_Nho,313
|
|
17
17
|
mercuto_client/ingester/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
mercuto_client/ingester/__main__.py,sha256=
|
|
18
|
+
mercuto_client/ingester/__main__.py,sha256=c7dKkl4Z3aHJuzbrbdAvxstNKzQ9eAem2za9GBvxQ_E,6999
|
|
19
19
|
mercuto_client/ingester/ftp.py,sha256=3-gMzoRCWjLZWeynjkwOXV59B4f0F2VnWp97fuUFTX4,4441
|
|
20
20
|
mercuto_client/ingester/mercuto.py,sha256=djlP9HVoBoB2R-pQVogyMvHpPpbWEjCX5vbMhlEhc8U,6077
|
|
21
|
-
mercuto_client/ingester/processor.py,sha256=
|
|
21
|
+
mercuto_client/ingester/processor.py,sha256=QM5zcX6QlXYAn4_cxqWSGHfgNICVrYcPXF3TGMVnjDU,11907
|
|
22
22
|
mercuto_client/ingester/parsers/__init__.py,sha256=lOt4TyP08hK56wl7XHMlqmj62mDE0Idx8UJL0wljtwM,1398
|
|
23
23
|
mercuto_client/ingester/parsers/campbell.py,sha256=S5enYbajVTm3zSQYkEP6JRVUw94Z7ky100j8p5qLCls,441
|
|
24
24
|
mercuto_client/ingester/parsers/generic_csv.py,sha256=v4rwO4oJb1Ue6zirO0TGtvewOSp9f6ZUT_sWvozvQHo,4051
|
|
@@ -34,8 +34,8 @@ mercuto_client/modules/core.py,sha256=KzSmKH71qK9wDM6I-LvXY9oA2nBJFLoQXawK2ei3uC
|
|
|
34
34
|
mercuto_client/modules/data.py,sha256=hMhzkkr0f7N9kVKvUQE65uXDpcCxGILcNUhZLSD3nD4,20742
|
|
35
35
|
mercuto_client/modules/fatigue.py,sha256=SPftwW5rMk6LcsIGWO8OHc9r6DA99qt0AyAVOaNRt_8,6397
|
|
36
36
|
mercuto_client/modules/identity.py,sha256=VeMGsq-s5B9xorP9G2TxwIDYUSyyDGuFAJ8Ilg7_mn4,7898
|
|
37
|
-
mercuto_client-0.3.
|
|
38
|
-
mercuto_client-0.3.
|
|
39
|
-
mercuto_client-0.3.
|
|
40
|
-
mercuto_client-0.3.
|
|
41
|
-
mercuto_client-0.3.
|
|
37
|
+
mercuto_client-0.3.1.dist-info/licenses/LICENSE,sha256=0R2QbX4pr5XSiwUc2JoGS7Ja4npcQHyZlGJsR-E73I8,32386
|
|
38
|
+
mercuto_client-0.3.1.dist-info/METADATA,sha256=OXr8wjeUoZF3X5CT8QzO0w559HTPCyY2qeUueRr22Mc,2421
|
|
39
|
+
mercuto_client-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
40
|
+
mercuto_client-0.3.1.dist-info/top_level.txt,sha256=ecV4spooVaOU8AlclvojxY1LzLW1byDywh-ayLHvKCs,15
|
|
41
|
+
mercuto_client-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|