Skip to content

Commit cdd0d26

Browse files
committed
adapt to easyrocks 2
1 parent 3dc347d commit cdd0d26

File tree

4 files changed

+67
-34
lines changed

4 files changed

+67
-34
lines changed

tests/main.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ def method_with_two_params(param1, param2=None):
3434
# Define three calls
3535
call1 = Call('method_without_params')
3636
call2 = Call('method_with_one_param', args=['value1'])
37-
call3 = Call('method_with_two_params', kwargs={'param1': 'value1', 'param2': 'value2'})
37+
call3 = Call('method_with_two_params',
38+
kwargs={
39+
'param1': 'value1',
40+
'param2': 'value2'
41+
})
3842

3943
# Add the three calls to the txlog atomically and check their indexes
4044
txlog.begin()

txlog/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
from .txlog import TxLog, Call
55
import logging
66

7-
__version__ = '0.0.5a'
7+
__version__ = '2.214.0'
88

99
logging.getLogger().setLevel(logging.INFO)
10-
logging.basicConfig(format='%(asctime)-15s [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
11-
logging.info(f'TxLog v{__version__}')
10+
logging.basicConfig(format='%(asctime)-15s [%(levelname)s] %(message)s',
11+
datefmt='%Y-%m-%d %H:%M:%S')

txlog/txlog.py

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4+
from .utils import get_timestamp_ms
45
from easyrocks import RocksDB, WriteBatch, utils
5-
import time
66
import builtins
77
from typing import Generator
88

9-
10-
def get_timestamp_ms():
11-
return int(round(time.time() * 1000))
9+
UINT_BYTES = 5
10+
MAX_UINT = 2**(UINT_BYTES * 8) - 1
1211

1312

1413
class Call:
@@ -82,7 +81,16 @@ def set_index(self, index):
8281

8382

8483
class TxLog:
85-
def __init__(self, path='./txlog_data', max_committed_items=0, committed_ttl_seconds=None):
84+
85+
CALL_PREFIX = b'\x00'
86+
OFFSET_PREFIX = b'\x01'
87+
INDEX_PREFIX = b'\x02'
88+
META_PREFIX = b'\x03'
89+
90+
def __init__(self,
91+
path='./txlog-data',
92+
max_committed_items=0,
93+
committed_ttl_seconds=None):
8694
self._batch_index = None
8795
self._write_batch = None
8896
self._committed_ttl_seconds = committed_ttl_seconds
@@ -101,22 +109,21 @@ def commit(self):
101109
def rollback(self):
102110
self._write_batch = None
103111

104-
@staticmethod
105-
def _get_call_key(index: int):
106-
return f'txlog_{utils.get_padded_int(index)}'
107-
108112
def commit_call(self, call: Call):
109-
new_write_batch = self._write_batch is None
110-
self.begin()
113+
is_new_write_batch = self._write_batch is None
114+
if is_new_write_batch:
115+
self.begin()
116+
111117
call._committed = True
112118
call._commitment_timestamp = get_timestamp_ms()
113119
self._update_call(call.index, call)
114120
self._increment_offset()
115-
if new_write_batch:
121+
122+
if is_new_write_batch:
116123
self.commit()
117124

118125
def get(self, index: int) -> Call:
119-
call_key = TxLog._get_call_key(index)
126+
call_key = self._get_call_key(index)
120127
return self._db.get(call_key)
121128

122129
def exec_uncommitted_calls(self, container_object=None):
@@ -127,7 +134,11 @@ def exec_uncommitted_calls(self, container_object=None):
127134
def add(self, call: Call):
128135
if not isinstance(call, Call):
129136
raise TypeError
137+
130138
index = self._get_next_index()
139+
if index > MAX_UINT:
140+
raise ValueError(index)
141+
131142
call.set_index(index)
132143
self._put_call(index, call)
133144
return index
@@ -141,26 +152,27 @@ def print_uncommitted_calls(self):
141152
print(call._method_name, call._args, call._kwargs)
142153

143154
def get_calls(self) -> Generator[Call, None, None]:
144-
for _, call in self._db.scan(prefix='txlog_'):
155+
for _, call in self._db.scan(prefix=self.CALL_PREFIX):
145156
yield call
146157

147158
def get_first_uncommitted_call(self) -> Call:
148159
next_offset = self._get_next_offset()
149160
if next_offset > self._get_index():
150161
return
151-
call_key = TxLog._get_call_key(next_offset)
162+
call_key = self._get_call_key(next_offset)
152163
return self._db.get(call_key)
153164

154165
def get_uncommitted_calls(self) -> Generator[Call, None, None]:
155166
first_uncommitted_call = self.get_first_uncommitted_call()
156167
if first_uncommitted_call is not None:
157-
for index in range(first_uncommitted_call.index, self._get_next_index()):
168+
for index in range(first_uncommitted_call.index,
169+
self._get_next_index()):
158170
yield self.get(index)
159171

160172
def truncate(self):
161173
if self._max_committed_items is not None:
162174
committed_calls_no = self.count_committed_calls()
163-
for key, call in self._db.scan(prefix='txlog_'):
175+
for key, call in self._db.scan(prefix=self.CALL_PREFIX):
164176
if not call.committed:
165177
break
166178

@@ -171,47 +183,50 @@ def truncate(self):
171183
committed_calls_no -= 1
172184

173185
if self._committed_ttl_seconds is not None:
174-
for key, call in self._db.scan(prefix='txlog_'):
186+
for key, call in self._db.scan(prefix=self.CALL_PREFIX):
175187
if not call.committed:
176188
break
177189

178-
min_timestamp = get_timestamp_ms() - self._committed_ttl_seconds * 1000
190+
min_timestamp = get_timestamp_ms() \
191+
- self._committed_ttl_seconds * 1000
179192
if call._creation_timestamp <= min_timestamp:
180193
self._db.delete(key)
181194

182195
def count_committed_calls(self) -> int:
183196
counter = 0
184-
for _, call in self._db.scan(prefix='txlog_'):
197+
for _, call in self._db.scan(prefix=self.CALL_PREFIX):
185198
if call.committed:
186199
counter += 1
187200
return counter
188201

189202
def count_calls(self) -> int:
190203
counter = 0
191-
for _, _ in self._db.scan(prefix='txlog_'):
204+
for _, _ in self._db.scan(prefix=self.CALL_PREFIX):
192205
counter += 1
193206
return counter
194207

208+
def _get_call_key(self, index: int):
209+
return self.CALL_PREFIX + utils.int_to_padded_bytes(index, UINT_BYTES)
210+
195211
def _update_call(self, index: int, call: Call):
196212
if not isinstance(call, Call):
197213
raise TypeError
198-
call_key = TxLog._get_call_key(index)
214+
call_key = self._get_call_key(index)
199215
self._db.put(call_key, call, write_batch=self._write_batch)
200216

201217
def _put_call(self, index: int, call: Call):
202218
if not isinstance(call, Call):
203219
raise TypeError
204220

205-
is_batch_new = False
206-
if self._write_batch is None:
207-
is_batch_new = True
221+
is_new_write_batch = self._write_batch is None
222+
if is_new_write_batch:
208223
self.begin()
209224

210-
call_key = TxLog._get_call_key(index)
225+
call_key = self._get_call_key(index)
211226
self._db.put(call_key, call, write_batch=self._write_batch)
212227
self._increment_index()
213228

214-
if is_batch_new:
229+
if is_new_write_batch:
215230
self.commit()
216231

217232
def _increment_offset(self):
@@ -236,16 +251,22 @@ def _get_next_index(self) -> int:
236251
return self._batch_index + 1
237252
return self._get_int_attribute('index') + 1
238253

254+
def _get_meta_key(self, attribute: str):
255+
return self.META_PREFIX + bytes(attribute, 'utf-8')
256+
239257
def _increment_int_attribute(self, attribute: str):
240258
if attribute == 'index' and self._write_batch is not None:
241259
self._batch_index += 1
242260
value = self._batch_index
243261
else:
244262
value = self._get_int_attribute(attribute) + 1
245-
self._db.put(f'meta_{attribute}', value, write_batch=self._write_batch)
263+
264+
key = self._get_meta_key(attribute)
265+
self._db.put(key, value, write_batch=self._write_batch)
246266

247267
def _get_int_attribute(self, attribute: str) -> int:
248-
value = self._db.get(f'meta_{attribute}')
268+
key = self._get_meta_key(attribute)
269+
value = self._db.get(key)
249270
if value is None:
250271
return -1
251-
return value
272+
return value

txlog/utils.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import time
5+
6+
7+
def get_timestamp_ms():
8+
return int(round(time.time() * 1000))

0 commit comments

Comments
 (0)