stratum-db 1.0.0__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.
- stratum/__init__.py +0 -0
- stratum/api.py +41 -0
- stratum/db.py +90 -0
- stratum/engine.py +220 -0
- stratum/grpc/__init__.py +0 -0
- stratum/grpc/server.py +45 -0
- stratum/grpc/stratum_pb2.py +48 -0
- stratum/grpc/stratum_pb2_grpc.py +183 -0
- stratum/init_db.py +6 -0
- stratum/memtable.py +59 -0
- stratum/metrics.py +54 -0
- stratum/models.py +33 -0
- stratum/sstable.py +253 -0
- stratum/wal.py +71 -0
- stratum_db-1.0.0.dist-info/METADATA +265 -0
- stratum_db-1.0.0.dist-info/RECORD +20 -0
- stratum_db-1.0.0.dist-info/WHEEL +5 -0
- stratum_db-1.0.0.dist-info/entry_points.txt +2 -0
- stratum_db-1.0.0.dist-info/licenses/LICENSE +21 -0
- stratum_db-1.0.0.dist-info/top_level.txt +1 -0
stratum/__init__.py
ADDED
|
File without changes
|
stratum/api.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import logging
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from dotenv import load_dotenv
|
|
6
|
+
|
|
7
|
+
load_dotenv()
|
|
8
|
+
|
|
9
|
+
def _get_config():
|
|
10
|
+
data_dir = Path(os.environ.get("STRATUM_DATA_DIR","./data"))
|
|
11
|
+
|
|
12
|
+
table_dir_raw = os.environ.get("STRATUM_TABLE_DIR")
|
|
13
|
+
table_dir = Path(table_dir_raw) if table_dir_raw else None
|
|
14
|
+
|
|
15
|
+
port_raw = os.environ.get("STRATUM_PORT","50051")
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
port = int(port_raw)
|
|
19
|
+
except ValueError:
|
|
20
|
+
raise ValueError(
|
|
21
|
+
f"STRATUM_PORT must be an integer, got {port_raw!r}"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
log_level_name = os.environ.get("STRATUM_LOG_LEVEL","INFO").upper()
|
|
25
|
+
log_level = getattr(logging, log_level_name)
|
|
26
|
+
if not isinstance(log_level, int):
|
|
27
|
+
raise ValueError(
|
|
28
|
+
f"STRATUM_LOG_LEVEL must be a valid level name, got {log_level_name!r}"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return data_dir, table_dir, port, log_level
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
data_dir, table_dir, port, log_level = _get_config()
|
|
35
|
+
logging.basicConfig(level=log_level)
|
|
36
|
+
|
|
37
|
+
from stratum.grpc.server import serve
|
|
38
|
+
serve(data_dir = data_dir, table_dir=table_dir, port=port)
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
stratum/db.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
_metadata_enabled = os.environ.get("STRATUM_METADATA_ENABLED", "false").strip().lower()
|
|
5
|
+
if _metadata_enabled not in {"1", "true", "yes", "on", "0", "false", "no", "off"}:
|
|
6
|
+
raise ValueError(
|
|
7
|
+
"STRATUM_METADATA_ENABLED must be a boolean value (true/false, 1/0, yes/no, or on/off)"
|
|
8
|
+
)
|
|
9
|
+
METADATA_ENABLED = _metadata_enabled in {"1", "true", "yes", "on"}
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if METADATA_ENABLED:
|
|
13
|
+
from sqlalchemy import create_engine
|
|
14
|
+
from sqlalchemy.orm import DeclarativeBase, sessionmaker
|
|
15
|
+
|
|
16
|
+
class Base(DeclarativeBase):
|
|
17
|
+
pass
|
|
18
|
+
else:
|
|
19
|
+
Base = None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_db_engine():
|
|
23
|
+
if METADATA_ENABLED:
|
|
24
|
+
database_url = os.environ.get("DATABASE_URL")
|
|
25
|
+
if not database_url:
|
|
26
|
+
raise RuntimeError(
|
|
27
|
+
"DATABASE_URL must be set when STRATUM_METADATA_ENABLED is enabled"
|
|
28
|
+
)
|
|
29
|
+
return create_engine(database_url, echo=True)
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
def get_session_factory():
|
|
33
|
+
db_engine = get_db_engine()
|
|
34
|
+
if db_engine is not None:
|
|
35
|
+
return sessionmaker(bind=db_engine)
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
def record_flush(filename, min_key, max_key, entry_count, file_size_bytes, created_at):
|
|
39
|
+
session_factory = get_session_factory()
|
|
40
|
+
if session_factory is None:
|
|
41
|
+
return None
|
|
42
|
+
session = session_factory()
|
|
43
|
+
from stratum.models import SSTableMeta
|
|
44
|
+
SSTableMetaEntry = SSTableMeta(
|
|
45
|
+
filename = filename,
|
|
46
|
+
min_key = min_key,
|
|
47
|
+
max_key = max_key,
|
|
48
|
+
entry_count = entry_count,
|
|
49
|
+
file_size_bytes = file_size_bytes,
|
|
50
|
+
created_at = created_at
|
|
51
|
+
)
|
|
52
|
+
try:
|
|
53
|
+
session.add(SSTableMetaEntry)
|
|
54
|
+
session.commit()
|
|
55
|
+
except Exception as e:
|
|
56
|
+
session.rollback()
|
|
57
|
+
print(f'[Metadata] record_flush failed: {e}')
|
|
58
|
+
finally:
|
|
59
|
+
session.close()
|
|
60
|
+
|
|
61
|
+
def record_compaction(status, started_at, completed_at, tombstones_dropped, input_filenames, output_fields):
|
|
62
|
+
session_factory = get_session_factory()
|
|
63
|
+
if session_factory is None:
|
|
64
|
+
return None
|
|
65
|
+
session = session_factory()
|
|
66
|
+
from stratum.models import SSTableMeta, CompactionJob
|
|
67
|
+
try:
|
|
68
|
+
input_rows = (
|
|
69
|
+
session.query(SSTableMeta)
|
|
70
|
+
.filter(SSTableMeta.filename.in_(input_filenames))
|
|
71
|
+
.all()
|
|
72
|
+
)
|
|
73
|
+
for row in input_rows:
|
|
74
|
+
row.is_active = False
|
|
75
|
+
|
|
76
|
+
output_row = SSTableMeta(**output_fields)
|
|
77
|
+
compactionJobEntry = CompactionJob(
|
|
78
|
+
status = status,
|
|
79
|
+
started_at = started_at,
|
|
80
|
+
completed_at = completed_at,
|
|
81
|
+
tombstones_dropped = tombstones_dropped,
|
|
82
|
+
output_sstable = output_row,
|
|
83
|
+
input_sstables = input_rows,)
|
|
84
|
+
session.add(compactionJobEntry)
|
|
85
|
+
session.commit()
|
|
86
|
+
except Exception as e:
|
|
87
|
+
session.rollback()
|
|
88
|
+
print(f'Metadata Write failed: {e}')
|
|
89
|
+
finally:
|
|
90
|
+
session.close()
|
stratum/engine.py
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from threading import RLock
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from sortedcontainers import SortedDict
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
import heapq
|
|
7
|
+
from itertools import groupby
|
|
8
|
+
|
|
9
|
+
from stratum.memtable import MemTable
|
|
10
|
+
from stratum.wal import WAL
|
|
11
|
+
from stratum.sstable import SSTable
|
|
12
|
+
from stratum import db
|
|
13
|
+
from stratum.metrics import MetricsRegistry
|
|
14
|
+
|
|
15
|
+
class Engine:
|
|
16
|
+
def __init__(self, data_dir, table_dir=None):
|
|
17
|
+
if not isinstance(data_dir, Path):
|
|
18
|
+
raise TypeError(
|
|
19
|
+
f"WAL requires a pathlib.Path, got {type(data_dir).__name__}. "
|
|
20
|
+
f"Wrap it with Path(...) at the call site."
|
|
21
|
+
)
|
|
22
|
+
if table_dir is None:
|
|
23
|
+
table_dir = data_dir
|
|
24
|
+
if not isinstance(table_dir, Path):
|
|
25
|
+
raise TypeError(
|
|
26
|
+
f"SSTable requires a pathlib.Path, got {type(table_dir).__name__}. "
|
|
27
|
+
f"Wrap it with Path(...) at the call site."
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
self.data_dir = data_dir
|
|
31
|
+
self.table_dir = table_dir
|
|
32
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
33
|
+
self.table_dir.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
self.memtable = MemTable()
|
|
36
|
+
self.wal = WAL(self.data_dir)
|
|
37
|
+
self._seq_no = 0
|
|
38
|
+
self.lock = RLock()
|
|
39
|
+
self.sstables = []
|
|
40
|
+
self.tableCount = 0
|
|
41
|
+
self.metrics = MetricsRegistry()
|
|
42
|
+
|
|
43
|
+
self._load_sstables()
|
|
44
|
+
self._recover()
|
|
45
|
+
self._update_metrics()
|
|
46
|
+
|
|
47
|
+
def _update_metrics(self):
|
|
48
|
+
self.metrics.set_gauge("sstables", len(self.sstables))
|
|
49
|
+
self.metrics.set_gauge("memtable_entries", len(self.memtable.items()))
|
|
50
|
+
|
|
51
|
+
def _load_sstables(self):
|
|
52
|
+
for sst_path in sorted(self.table_dir.glob("*.sst")):
|
|
53
|
+
idx_path = sst_path.with_suffix('.idx')
|
|
54
|
+
if not idx_path.exists():
|
|
55
|
+
raise FileNotFoundError(f"Could not find {idx_path}")
|
|
56
|
+
self.sstables.append(SSTable.from_file(sst_path, idx_path))
|
|
57
|
+
match = re.match(r"^(\d+)", sst_path.name)
|
|
58
|
+
if match:
|
|
59
|
+
self.tableCount = max(self.tableCount, int(match.group(1)) + 1)
|
|
60
|
+
|
|
61
|
+
def _recover(self):
|
|
62
|
+
for seq_no, op_type, key, value in self.wal.replay():
|
|
63
|
+
self._seq_no = seq_no
|
|
64
|
+
if op_type == 1:
|
|
65
|
+
self.memtable.put(key, value, self._seq_no)
|
|
66
|
+
else:
|
|
67
|
+
self.memtable.delete(key, self._seq_no)
|
|
68
|
+
|
|
69
|
+
def put(self, key, value):
|
|
70
|
+
self.metrics.increment("puts_total")
|
|
71
|
+
with self.lock:
|
|
72
|
+
if self.memtable.is_full():
|
|
73
|
+
self.write_table()
|
|
74
|
+
self._seq_no += 1
|
|
75
|
+
self.wal.append(self._seq_no, 1, key, value)
|
|
76
|
+
self.memtable.put(key, value, self._seq_no)
|
|
77
|
+
self._update_metrics()
|
|
78
|
+
|
|
79
|
+
def write_table(self):
|
|
80
|
+
data = self.memtable.items()
|
|
81
|
+
self.tableCount += 1
|
|
82
|
+
new_sstable = SSTable.flush(self.table_dir, self.tableCount, data)
|
|
83
|
+
if db.METADATA_ENABLED:
|
|
84
|
+
created_at = datetime.now(timezone.utc)
|
|
85
|
+
db.record_flush(
|
|
86
|
+
filename=new_sstable.sst_path.name,
|
|
87
|
+
min_key=new_sstable.min_key,
|
|
88
|
+
max_key=new_sstable.max_key,
|
|
89
|
+
entry_count=new_sstable.entry_count,
|
|
90
|
+
file_size_bytes=new_sstable.file_size_bytes,
|
|
91
|
+
created_at=created_at
|
|
92
|
+
)
|
|
93
|
+
self.sstables.append(new_sstable)
|
|
94
|
+
self.wal.truncate()
|
|
95
|
+
self.memtable = MemTable()
|
|
96
|
+
self.metrics.increment("flushes_total")
|
|
97
|
+
self._update_metrics()
|
|
98
|
+
|
|
99
|
+
def delete(self, key):
|
|
100
|
+
self.metrics.increment("deletes_total")
|
|
101
|
+
with self.lock:
|
|
102
|
+
self._seq_no += 1
|
|
103
|
+
self.wal.append(self._seq_no, 2, key, b"")
|
|
104
|
+
self.memtable.delete(key,self._seq_no)
|
|
105
|
+
self._update_metrics()
|
|
106
|
+
|
|
107
|
+
def get(self, key):
|
|
108
|
+
self.metrics.increment("gets_total")
|
|
109
|
+
with self.lock:
|
|
110
|
+
record = self.memtable.get_record(key)
|
|
111
|
+
if record is not None:
|
|
112
|
+
value, _, deleted = record
|
|
113
|
+
return None if deleted else value
|
|
114
|
+
|
|
115
|
+
for sstable in reversed(self.sstables):
|
|
116
|
+
if sstable.min_key is not None and not (sstable.min_key <= key <= sstable.max_key):
|
|
117
|
+
continue
|
|
118
|
+
if not sstable.might_contain(key):
|
|
119
|
+
continue
|
|
120
|
+
results = sstable.search(key)
|
|
121
|
+
if results:
|
|
122
|
+
_, value, _, deleted = results[0]
|
|
123
|
+
return None if deleted else value
|
|
124
|
+
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
def scan(self, start_key, end_key):
|
|
128
|
+
self.metrics.increment("scans_total")
|
|
129
|
+
if start_key > end_key:
|
|
130
|
+
return
|
|
131
|
+
|
|
132
|
+
with self.lock:
|
|
133
|
+
sstables = list(self.sstables)
|
|
134
|
+
memtable_items = self.memtable.items()
|
|
135
|
+
|
|
136
|
+
sources = []
|
|
137
|
+
|
|
138
|
+
for table in sstables:
|
|
139
|
+
if table.entry_count == 0:
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
if table.max_key < start_key or table.min_key > end_key:
|
|
143
|
+
continue
|
|
144
|
+
|
|
145
|
+
sources.append(table.scan(start_key, end_key))
|
|
146
|
+
|
|
147
|
+
sources.append(
|
|
148
|
+
(key, value, seq_no, deleted) for key, (value, seq_no, deleted) in memtable_items if start_key <= key <= end_key
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
merged = heapq.merge(*sources, key = lambda entry: entry [0])
|
|
152
|
+
|
|
153
|
+
for key, entries in groupby(merged, key= lambda entry: entry[0]):
|
|
154
|
+
newest = max(entries, key = lambda entry: entry[2])
|
|
155
|
+
if not newest[3]:
|
|
156
|
+
yield key, newest[1]
|
|
157
|
+
|
|
158
|
+
def compact(self):
|
|
159
|
+
self.metrics.increment("compactions_total")
|
|
160
|
+
with self.lock:
|
|
161
|
+
started_at = datetime.now(timezone.utc)
|
|
162
|
+
entries = SortedDict()
|
|
163
|
+
input_filenames = []
|
|
164
|
+
for table in self.sstables:
|
|
165
|
+
input_filenames.append(table.sst_path.name)
|
|
166
|
+
table_entries = table.scan(table.min_key, table.max_key)
|
|
167
|
+
for key, val, seq_no, deleted in table_entries:
|
|
168
|
+
old = entries.get(key)
|
|
169
|
+
if old is None:
|
|
170
|
+
entries[key] = (val, seq_no, deleted)
|
|
171
|
+
else:
|
|
172
|
+
if seq_no > entries[key][1]:
|
|
173
|
+
entries[key] = (val, seq_no, deleted)
|
|
174
|
+
del_keys = []
|
|
175
|
+
for key, entry in entries.items():
|
|
176
|
+
if entry[2]:
|
|
177
|
+
del_keys.append(key)
|
|
178
|
+
for key in del_keys:
|
|
179
|
+
del entries[key]
|
|
180
|
+
|
|
181
|
+
self.tableCount += 1
|
|
182
|
+
created_at = datetime.now(timezone.utc)
|
|
183
|
+
new_table = SSTable.flush(self.table_dir, self.tableCount, entries.items())
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if new_table.min_key is None:
|
|
188
|
+
new_table.min_key = b""
|
|
189
|
+
new_table.max_key = b""
|
|
190
|
+
|
|
191
|
+
old_sst_paths = [t.sst_path for t in self.sstables]
|
|
192
|
+
old_idx_paths = [t.idx_path for t in self.sstables]
|
|
193
|
+
self.sstables = [new_table]
|
|
194
|
+
output_fields = {
|
|
195
|
+
'filename':new_table.sst_path.name,
|
|
196
|
+
'min_key':new_table.min_key,
|
|
197
|
+
'max_key':new_table.max_key,
|
|
198
|
+
'entry_count':new_table.entry_count,
|
|
199
|
+
'file_size_bytes':new_table.file_size_bytes,
|
|
200
|
+
'created_at':created_at
|
|
201
|
+
}
|
|
202
|
+
if db.METADATA_ENABLED:
|
|
203
|
+
completed_at = datetime.now(timezone.utc)
|
|
204
|
+
db.record_compaction(
|
|
205
|
+
status="Completed",
|
|
206
|
+
started_at=started_at,
|
|
207
|
+
completed_at=completed_at,
|
|
208
|
+
tombstones_dropped=len(del_keys),
|
|
209
|
+
input_filenames=input_filenames,
|
|
210
|
+
output_fields=output_fields
|
|
211
|
+
)
|
|
212
|
+
for sst_path, idx_path in zip(old_sst_paths,old_idx_paths):
|
|
213
|
+
try:
|
|
214
|
+
Path(sst_path).unlink()
|
|
215
|
+
except OSError as e:
|
|
216
|
+
print(f"Failed to delete {sst_path}: {e}")
|
|
217
|
+
try:
|
|
218
|
+
Path(idx_path).unlink()
|
|
219
|
+
except OSError as e:
|
|
220
|
+
print(f"Failed to delete {idx_path}: {e}")
|
stratum/grpc/__init__.py
ADDED
|
File without changes
|
stratum/grpc/server.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from concurrent import futures
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import grpc
|
|
4
|
+
|
|
5
|
+
from stratum.grpc import stratum_pb2,stratum_pb2_grpc
|
|
6
|
+
from stratum.engine import Engine
|
|
7
|
+
|
|
8
|
+
class StratumServicer(stratum_pb2_grpc.StratumServicer):
|
|
9
|
+
def __init__(self, engine):
|
|
10
|
+
self.engine = engine
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def _require_key(key, context, field_name):
|
|
14
|
+
if not key:
|
|
15
|
+
context.abort(
|
|
16
|
+
grpc.StatusCode.INVALID_ARGUMENT,
|
|
17
|
+
f"{field_name} must not be empty",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def Get(self, request, context):
|
|
21
|
+
self._require_key(request.key, context, "key")
|
|
22
|
+
value = self.engine.get(request.key)
|
|
23
|
+
if value is None:
|
|
24
|
+
return stratum_pb2.GetResponse(found = False)
|
|
25
|
+
return stratum_pb2.GetResponse(value=value, found=True)
|
|
26
|
+
|
|
27
|
+
def Put(self, request, context):
|
|
28
|
+
self._require_key(request.key, context, "key")
|
|
29
|
+
self.engine.put(request.key, request.value)
|
|
30
|
+
return stratum_pb2.PutResponse(success=True)
|
|
31
|
+
|
|
32
|
+
def Scan(self, request, context):
|
|
33
|
+
self._require_key(request.start_key, context, "start_key")
|
|
34
|
+
self._require_key(request.end_key, context, "end_key")
|
|
35
|
+
for key, value in self.engine.scan(request.start_key, request.end_key):
|
|
36
|
+
yield stratum_pb2.KVPair(key=key, value=value)
|
|
37
|
+
|
|
38
|
+
def serve(data_dir, table_dir=None, port=50051):
|
|
39
|
+
engine = Engine(data_dir = data_dir, table_dir= table_dir)
|
|
40
|
+
server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
|
|
41
|
+
stratum_pb2_grpc.add_StratumServicer_to_server(StratumServicer(engine), server)
|
|
42
|
+
server.add_insecure_port(f'[::]:{port}')
|
|
43
|
+
server.start()
|
|
44
|
+
print(f"gRPC server running on port {port}")
|
|
45
|
+
server.wait_for_termination()
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: stratum.proto
|
|
5
|
+
# Protobuf Python Version: 7.35.1
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
7,
|
|
15
|
+
35,
|
|
16
|
+
1,
|
|
17
|
+
'',
|
|
18
|
+
'stratum.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rstratum.proto\x12\x07stratum\"\x19\n\nGetRequest\x12\x0b\n\x03key\x18\x01 \x01(\x0c\"+\n\x0bGetResponse\x12\r\n\x05value\x18\x01 \x01(\x0c\x12\r\n\x05\x66ound\x18\x02 \x01(\x08\"(\n\nPutRequest\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05value\x18\x02 \x01(\x0c\"\x1e\n\x0bPutResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"1\n\x0bScanRequest\x12\x11\n\tstart_key\x18\x01 \x01(\x0c\x12\x0f\n\x07\x65nd_key\x18\x02 \x01(\x0c\"$\n\x06KVPair\x12\x0b\n\x03key\x18\x01 \x01(\x0c\x12\r\n\x05value\x18\x02 \x01(\x0c\x32\x9e\x01\n\x07Stratum\x12\x30\n\x03Get\x12\x13.stratum.GetRequest\x1a\x14.stratum.GetResponse\x12\x30\n\x03Put\x12\x13.stratum.PutRequest\x1a\x14.stratum.PutResponse\x12/\n\x04Scan\x12\x14.stratum.ScanRequest\x1a\x0f.stratum.KVPair0\x01\x62\x06proto3')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'stratum_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
DESCRIPTOR._loaded_options = None
|
|
34
|
+
_globals['_GETREQUEST']._serialized_start=26
|
|
35
|
+
_globals['_GETREQUEST']._serialized_end=51
|
|
36
|
+
_globals['_GETRESPONSE']._serialized_start=53
|
|
37
|
+
_globals['_GETRESPONSE']._serialized_end=96
|
|
38
|
+
_globals['_PUTREQUEST']._serialized_start=98
|
|
39
|
+
_globals['_PUTREQUEST']._serialized_end=138
|
|
40
|
+
_globals['_PUTRESPONSE']._serialized_start=140
|
|
41
|
+
_globals['_PUTRESPONSE']._serialized_end=170
|
|
42
|
+
_globals['_SCANREQUEST']._serialized_start=172
|
|
43
|
+
_globals['_SCANREQUEST']._serialized_end=221
|
|
44
|
+
_globals['_KVPAIR']._serialized_start=223
|
|
45
|
+
_globals['_KVPAIR']._serialized_end=259
|
|
46
|
+
_globals['_STRATUM']._serialized_start=262
|
|
47
|
+
_globals['_STRATUM']._serialized_end=420
|
|
48
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
from . import stratum_pb2 as stratum__pb2
|
|
7
|
+
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.83.1'
|
|
9
|
+
GRPC_VERSION = grpc.__version__
|
|
10
|
+
_version_not_supported = False
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from grpc._utilities import first_version_is_lower
|
|
14
|
+
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
|
15
|
+
except ImportError:
|
|
16
|
+
_version_not_supported = True
|
|
17
|
+
|
|
18
|
+
if _version_not_supported:
|
|
19
|
+
raise RuntimeError(
|
|
20
|
+
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
+
+ ' but the generated code in stratum_pb2_grpc.py depends on'
|
|
22
|
+
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
|
+
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
|
+
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class StratumStub:
|
|
29
|
+
"""Missing associated documentation comment in .proto file."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, channel):
|
|
32
|
+
"""Constructor.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
channel: A grpc.Channel.
|
|
36
|
+
"""
|
|
37
|
+
self.Get = channel.unary_unary(
|
|
38
|
+
'/stratum.Stratum/Get',
|
|
39
|
+
request_serializer=stratum__pb2.GetRequest.SerializeToString,
|
|
40
|
+
response_deserializer=stratum__pb2.GetResponse.FromString,
|
|
41
|
+
_registered_method=True)
|
|
42
|
+
self.Put = channel.unary_unary(
|
|
43
|
+
'/stratum.Stratum/Put',
|
|
44
|
+
request_serializer=stratum__pb2.PutRequest.SerializeToString,
|
|
45
|
+
response_deserializer=stratum__pb2.PutResponse.FromString,
|
|
46
|
+
_registered_method=True)
|
|
47
|
+
self.Scan = channel.unary_stream(
|
|
48
|
+
'/stratum.Stratum/Scan',
|
|
49
|
+
request_serializer=stratum__pb2.ScanRequest.SerializeToString,
|
|
50
|
+
response_deserializer=stratum__pb2.KVPair.FromString,
|
|
51
|
+
_registered_method=True)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class StratumServicer:
|
|
55
|
+
"""Missing associated documentation comment in .proto file."""
|
|
56
|
+
|
|
57
|
+
def Get(self, request, context):
|
|
58
|
+
"""Missing associated documentation comment in .proto file."""
|
|
59
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
60
|
+
context.set_details('Method not implemented!')
|
|
61
|
+
raise NotImplementedError('Method not implemented!')
|
|
62
|
+
|
|
63
|
+
def Put(self, request, context):
|
|
64
|
+
"""Missing associated documentation comment in .proto file."""
|
|
65
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
66
|
+
context.set_details('Method not implemented!')
|
|
67
|
+
raise NotImplementedError('Method not implemented!')
|
|
68
|
+
|
|
69
|
+
def Scan(self, request, context):
|
|
70
|
+
"""Missing associated documentation comment in .proto file."""
|
|
71
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
72
|
+
context.set_details('Method not implemented!')
|
|
73
|
+
raise NotImplementedError('Method not implemented!')
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def add_StratumServicer_to_server(servicer, server):
|
|
77
|
+
rpc_method_handlers = {
|
|
78
|
+
'Get': grpc.unary_unary_rpc_method_handler(
|
|
79
|
+
servicer.Get,
|
|
80
|
+
request_deserializer=stratum__pb2.GetRequest.FromString,
|
|
81
|
+
response_serializer=stratum__pb2.GetResponse.SerializeToString,
|
|
82
|
+
),
|
|
83
|
+
'Put': grpc.unary_unary_rpc_method_handler(
|
|
84
|
+
servicer.Put,
|
|
85
|
+
request_deserializer=stratum__pb2.PutRequest.FromString,
|
|
86
|
+
response_serializer=stratum__pb2.PutResponse.SerializeToString,
|
|
87
|
+
),
|
|
88
|
+
'Scan': grpc.unary_stream_rpc_method_handler(
|
|
89
|
+
servicer.Scan,
|
|
90
|
+
request_deserializer=stratum__pb2.ScanRequest.FromString,
|
|
91
|
+
response_serializer=stratum__pb2.KVPair.SerializeToString,
|
|
92
|
+
),
|
|
93
|
+
}
|
|
94
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
95
|
+
'stratum.Stratum', rpc_method_handlers)
|
|
96
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
97
|
+
server.add_registered_method_handlers('stratum.Stratum', rpc_method_handlers)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# This class is part of an EXPERIMENTAL API.
|
|
101
|
+
class Stratum:
|
|
102
|
+
"""Missing associated documentation comment in .proto file."""
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def Get(request,
|
|
106
|
+
target,
|
|
107
|
+
options=(),
|
|
108
|
+
channel_credentials=None,
|
|
109
|
+
call_credentials=None,
|
|
110
|
+
insecure=False,
|
|
111
|
+
compression=None,
|
|
112
|
+
wait_for_ready=None,
|
|
113
|
+
timeout=None,
|
|
114
|
+
metadata=None):
|
|
115
|
+
return grpc.experimental.unary_unary(
|
|
116
|
+
request,
|
|
117
|
+
target,
|
|
118
|
+
'/stratum.Stratum/Get',
|
|
119
|
+
stratum__pb2.GetRequest.SerializeToString,
|
|
120
|
+
stratum__pb2.GetResponse.FromString,
|
|
121
|
+
options,
|
|
122
|
+
channel_credentials,
|
|
123
|
+
insecure,
|
|
124
|
+
call_credentials,
|
|
125
|
+
compression,
|
|
126
|
+
wait_for_ready,
|
|
127
|
+
timeout,
|
|
128
|
+
metadata,
|
|
129
|
+
_registered_method=True)
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def Put(request,
|
|
133
|
+
target,
|
|
134
|
+
options=(),
|
|
135
|
+
channel_credentials=None,
|
|
136
|
+
call_credentials=None,
|
|
137
|
+
insecure=False,
|
|
138
|
+
compression=None,
|
|
139
|
+
wait_for_ready=None,
|
|
140
|
+
timeout=None,
|
|
141
|
+
metadata=None):
|
|
142
|
+
return grpc.experimental.unary_unary(
|
|
143
|
+
request,
|
|
144
|
+
target,
|
|
145
|
+
'/stratum.Stratum/Put',
|
|
146
|
+
stratum__pb2.PutRequest.SerializeToString,
|
|
147
|
+
stratum__pb2.PutResponse.FromString,
|
|
148
|
+
options,
|
|
149
|
+
channel_credentials,
|
|
150
|
+
insecure,
|
|
151
|
+
call_credentials,
|
|
152
|
+
compression,
|
|
153
|
+
wait_for_ready,
|
|
154
|
+
timeout,
|
|
155
|
+
metadata,
|
|
156
|
+
_registered_method=True)
|
|
157
|
+
|
|
158
|
+
@staticmethod
|
|
159
|
+
def Scan(request,
|
|
160
|
+
target,
|
|
161
|
+
options=(),
|
|
162
|
+
channel_credentials=None,
|
|
163
|
+
call_credentials=None,
|
|
164
|
+
insecure=False,
|
|
165
|
+
compression=None,
|
|
166
|
+
wait_for_ready=None,
|
|
167
|
+
timeout=None,
|
|
168
|
+
metadata=None):
|
|
169
|
+
return grpc.experimental.unary_stream(
|
|
170
|
+
request,
|
|
171
|
+
target,
|
|
172
|
+
'/stratum.Stratum/Scan',
|
|
173
|
+
stratum__pb2.ScanRequest.SerializeToString,
|
|
174
|
+
stratum__pb2.KVPair.FromString,
|
|
175
|
+
options,
|
|
176
|
+
channel_credentials,
|
|
177
|
+
insecure,
|
|
178
|
+
call_credentials,
|
|
179
|
+
compression,
|
|
180
|
+
wait_for_ready,
|
|
181
|
+
timeout,
|
|
182
|
+
metadata,
|
|
183
|
+
_registered_method=True)
|