deepfos 1.1.60__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.
- deepfos/__init__.py +6 -0
- deepfos/_version.py +21 -0
- deepfos/algo/__init__.py +0 -0
- deepfos/algo/graph.py +171 -0
- deepfos/algo/segtree.py +31 -0
- deepfos/api/V1_1/__init__.py +0 -0
- deepfos/api/V1_1/business_model.py +119 -0
- deepfos/api/V1_1/dimension.py +599 -0
- deepfos/api/V1_1/models/__init__.py +0 -0
- deepfos/api/V1_1/models/business_model.py +1033 -0
- deepfos/api/V1_1/models/dimension.py +2768 -0
- deepfos/api/V1_2/__init__.py +0 -0
- deepfos/api/V1_2/dimension.py +285 -0
- deepfos/api/V1_2/models/__init__.py +0 -0
- deepfos/api/V1_2/models/dimension.py +2923 -0
- deepfos/api/__init__.py +0 -0
- deepfos/api/account.py +167 -0
- deepfos/api/accounting_engines.py +147 -0
- deepfos/api/app.py +626 -0
- deepfos/api/approval_process.py +198 -0
- deepfos/api/base.py +983 -0
- deepfos/api/business_model.py +160 -0
- deepfos/api/consolidation.py +129 -0
- deepfos/api/consolidation_process.py +106 -0
- deepfos/api/datatable.py +341 -0
- deepfos/api/deep_pipeline.py +61 -0
- deepfos/api/deepconnector.py +36 -0
- deepfos/api/deepfos_task.py +92 -0
- deepfos/api/deepmodel.py +188 -0
- deepfos/api/dimension.py +486 -0
- deepfos/api/financial_model.py +319 -0
- deepfos/api/journal_model.py +119 -0
- deepfos/api/journal_template.py +132 -0
- deepfos/api/memory_financial_model.py +98 -0
- deepfos/api/models/__init__.py +3 -0
- deepfos/api/models/account.py +483 -0
- deepfos/api/models/accounting_engines.py +756 -0
- deepfos/api/models/app.py +1338 -0
- deepfos/api/models/approval_process.py +1043 -0
- deepfos/api/models/base.py +234 -0
- deepfos/api/models/business_model.py +805 -0
- deepfos/api/models/consolidation.py +711 -0
- deepfos/api/models/consolidation_process.py +248 -0
- deepfos/api/models/datatable_mysql.py +427 -0
- deepfos/api/models/deep_pipeline.py +55 -0
- deepfos/api/models/deepconnector.py +28 -0
- deepfos/api/models/deepfos_task.py +386 -0
- deepfos/api/models/deepmodel.py +308 -0
- deepfos/api/models/dimension.py +1576 -0
- deepfos/api/models/financial_model.py +1796 -0
- deepfos/api/models/journal_model.py +341 -0
- deepfos/api/models/journal_template.py +854 -0
- deepfos/api/models/memory_financial_model.py +478 -0
- deepfos/api/models/platform.py +178 -0
- deepfos/api/models/python.py +221 -0
- deepfos/api/models/reconciliation_engine.py +411 -0
- deepfos/api/models/reconciliation_report.py +161 -0
- deepfos/api/models/role_strategy.py +884 -0
- deepfos/api/models/smartlist.py +237 -0
- deepfos/api/models/space.py +1137 -0
- deepfos/api/models/system.py +1065 -0
- deepfos/api/models/variable.py +463 -0
- deepfos/api/models/workflow.py +946 -0
- deepfos/api/platform.py +199 -0
- deepfos/api/python.py +90 -0
- deepfos/api/reconciliation_engine.py +181 -0
- deepfos/api/reconciliation_report.py +64 -0
- deepfos/api/role_strategy.py +234 -0
- deepfos/api/smartlist.py +69 -0
- deepfos/api/space.py +582 -0
- deepfos/api/system.py +372 -0
- deepfos/api/variable.py +154 -0
- deepfos/api/workflow.py +264 -0
- deepfos/boost/__init__.py +6 -0
- deepfos/boost/py_jstream.py +89 -0
- deepfos/boost/py_pandas.py +20 -0
- deepfos/cache.py +121 -0
- deepfos/config.py +6 -0
- deepfos/core/__init__.py +27 -0
- deepfos/core/cube/__init__.py +10 -0
- deepfos/core/cube/_base.py +462 -0
- deepfos/core/cube/constants.py +21 -0
- deepfos/core/cube/cube.py +408 -0
- deepfos/core/cube/formula.py +707 -0
- deepfos/core/cube/syscube.py +532 -0
- deepfos/core/cube/typing.py +7 -0
- deepfos/core/cube/utils.py +238 -0
- deepfos/core/dimension/__init__.py +11 -0
- deepfos/core/dimension/_base.py +506 -0
- deepfos/core/dimension/dimcreator.py +184 -0
- deepfos/core/dimension/dimension.py +472 -0
- deepfos/core/dimension/dimexpr.py +271 -0
- deepfos/core/dimension/dimmember.py +155 -0
- deepfos/core/dimension/eledimension.py +22 -0
- deepfos/core/dimension/filters.py +99 -0
- deepfos/core/dimension/sysdimension.py +168 -0
- deepfos/core/logictable/__init__.py +5 -0
- deepfos/core/logictable/_cache.py +141 -0
- deepfos/core/logictable/_operator.py +663 -0
- deepfos/core/logictable/nodemixin.py +673 -0
- deepfos/core/logictable/sqlcondition.py +609 -0
- deepfos/core/logictable/tablemodel.py +497 -0
- deepfos/db/__init__.py +36 -0
- deepfos/db/cipher.py +660 -0
- deepfos/db/clickhouse.py +191 -0
- deepfos/db/connector.py +195 -0
- deepfos/db/daclickhouse.py +171 -0
- deepfos/db/dameng.py +101 -0
- deepfos/db/damysql.py +189 -0
- deepfos/db/dbkits.py +358 -0
- deepfos/db/deepengine.py +99 -0
- deepfos/db/deepmodel.py +82 -0
- deepfos/db/deepmodel_kingbase.py +83 -0
- deepfos/db/edb.py +214 -0
- deepfos/db/gauss.py +83 -0
- deepfos/db/kingbase.py +83 -0
- deepfos/db/mysql.py +184 -0
- deepfos/db/oracle.py +131 -0
- deepfos/db/postgresql.py +192 -0
- deepfos/db/sqlserver.py +99 -0
- deepfos/db/utils.py +135 -0
- deepfos/element/__init__.py +89 -0
- deepfos/element/accounting.py +348 -0
- deepfos/element/apvlprocess.py +215 -0
- deepfos/element/base.py +398 -0
- deepfos/element/bizmodel.py +1269 -0
- deepfos/element/datatable.py +2467 -0
- deepfos/element/deep_pipeline.py +186 -0
- deepfos/element/deepconnector.py +59 -0
- deepfos/element/deepmodel.py +1806 -0
- deepfos/element/dimension.py +1254 -0
- deepfos/element/fact_table.py +427 -0
- deepfos/element/finmodel.py +1485 -0
- deepfos/element/journal.py +840 -0
- deepfos/element/journal_template.py +943 -0
- deepfos/element/pyscript.py +412 -0
- deepfos/element/reconciliation.py +553 -0
- deepfos/element/rolestrategy.py +243 -0
- deepfos/element/smartlist.py +457 -0
- deepfos/element/variable.py +756 -0
- deepfos/element/workflow.py +560 -0
- deepfos/exceptions/__init__.py +239 -0
- deepfos/exceptions/hook.py +86 -0
- deepfos/lazy.py +104 -0
- deepfos/lazy_import.py +84 -0
- deepfos/lib/__init__.py +0 -0
- deepfos/lib/_javaobj.py +366 -0
- deepfos/lib/asynchronous.py +879 -0
- deepfos/lib/concurrency.py +107 -0
- deepfos/lib/constant.py +39 -0
- deepfos/lib/decorator.py +310 -0
- deepfos/lib/deepchart.py +778 -0
- deepfos/lib/deepux.py +477 -0
- deepfos/lib/discovery.py +273 -0
- deepfos/lib/edb_lexer.py +789 -0
- deepfos/lib/eureka.py +156 -0
- deepfos/lib/filterparser.py +751 -0
- deepfos/lib/httpcli.py +106 -0
- deepfos/lib/jsonstreamer.py +80 -0
- deepfos/lib/msg.py +394 -0
- deepfos/lib/nacos.py +225 -0
- deepfos/lib/patch.py +92 -0
- deepfos/lib/redis.py +241 -0
- deepfos/lib/serutils.py +181 -0
- deepfos/lib/stopwatch.py +99 -0
- deepfos/lib/subtask.py +572 -0
- deepfos/lib/sysutils.py +703 -0
- deepfos/lib/utils.py +1003 -0
- deepfos/local.py +160 -0
- deepfos/options.py +670 -0
- deepfos/translation.py +237 -0
- deepfos-1.1.60.dist-info/METADATA +33 -0
- deepfos-1.1.60.dist-info/RECORD +175 -0
- deepfos-1.1.60.dist-info/WHEEL +5 -0
- deepfos-1.1.60.dist-info/top_level.txt +1 -0
deepfos/lib/discovery.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
from functools import partial
|
|
5
|
+
from itertools import chain
|
|
6
|
+
from random import randint
|
|
7
|
+
from typing import Dict, List
|
|
8
|
+
|
|
9
|
+
from loguru import logger
|
|
10
|
+
|
|
11
|
+
from deepfos import OPTION
|
|
12
|
+
from deepfos.exceptions import APIRequestError
|
|
13
|
+
from deepfos.lib.asynchronous import evloop
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def poll_event(
|
|
17
|
+
event: asyncio.Event,
|
|
18
|
+
interval: int
|
|
19
|
+
):
|
|
20
|
+
fut = asyncio.ensure_future(event.wait())
|
|
21
|
+
|
|
22
|
+
async def poller():
|
|
23
|
+
done, _ = await asyncio.wait(
|
|
24
|
+
[fut],
|
|
25
|
+
timeout=interval
|
|
26
|
+
)
|
|
27
|
+
return bool(done)
|
|
28
|
+
|
|
29
|
+
while not (await poller()):
|
|
30
|
+
yield
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class AbstractServiceCache(ABC):
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def add(self, item): pass
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def delete(self, item): pass
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def punish(self, item): pass
|
|
42
|
+
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def reward(self, item): pass
|
|
45
|
+
|
|
46
|
+
@abstractmethod
|
|
47
|
+
def pick_best(self): pass
|
|
48
|
+
|
|
49
|
+
@abstractmethod
|
|
50
|
+
def __len__(self) -> int: pass
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def __iter__(self): pass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class RankedCache(AbstractServiceCache):
|
|
57
|
+
def __init__(self):
|
|
58
|
+
self.__rank: Dict[str, int] = {}
|
|
59
|
+
|
|
60
|
+
def add(self, item):
|
|
61
|
+
"""
|
|
62
|
+
将instace增加到缓存中:对实例的add和update操作都适用
|
|
63
|
+
"""
|
|
64
|
+
if item in self.__rank:
|
|
65
|
+
return
|
|
66
|
+
self.__rank[item] = 0
|
|
67
|
+
|
|
68
|
+
def delete(self, item):
|
|
69
|
+
"""
|
|
70
|
+
将instance从缓存中删除
|
|
71
|
+
"""
|
|
72
|
+
if item not in self.__rank:
|
|
73
|
+
return
|
|
74
|
+
del self.__rank[item]
|
|
75
|
+
|
|
76
|
+
def punish(self, item):
|
|
77
|
+
if item not in self.__rank:
|
|
78
|
+
return
|
|
79
|
+
self.__rank[item] = -1
|
|
80
|
+
|
|
81
|
+
def reward(self, item):
|
|
82
|
+
if item not in self.__rank:
|
|
83
|
+
return
|
|
84
|
+
self.__rank[item] += 1
|
|
85
|
+
|
|
86
|
+
def pick_best(self):
|
|
87
|
+
ordered = sorted(self.__rank.items(), key=lambda x: x[1])
|
|
88
|
+
return ordered[-1][0]
|
|
89
|
+
|
|
90
|
+
def __len__(self):
|
|
91
|
+
return len(self.__rank)
|
|
92
|
+
|
|
93
|
+
def __bool__(self):
|
|
94
|
+
return bool(self.__rank)
|
|
95
|
+
|
|
96
|
+
def __iter__(self):
|
|
97
|
+
return self.__rank.keys().__iter__()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class RoundRobinCache(AbstractServiceCache):
|
|
101
|
+
def __init__(self):
|
|
102
|
+
self._active: List[str] = []
|
|
103
|
+
self._dead_time: Dict[str, int] = defaultdict(int)
|
|
104
|
+
self._next_idx = -1
|
|
105
|
+
|
|
106
|
+
def add(self, item):
|
|
107
|
+
if item not in self._active:
|
|
108
|
+
self._active.append(item)
|
|
109
|
+
self._dead_time.pop(item, None)
|
|
110
|
+
|
|
111
|
+
def delete(self, item):
|
|
112
|
+
if item in self._active:
|
|
113
|
+
self._active.remove(item)
|
|
114
|
+
self._dead_time.pop(item, None)
|
|
115
|
+
|
|
116
|
+
def _change_idx(self):
|
|
117
|
+
# len(self._active) should be larger than 0 since pick-best only be called
|
|
118
|
+
# when bool(self) is true
|
|
119
|
+
self._next_idx = (self._next_idx + 1) % len(self._active)
|
|
120
|
+
|
|
121
|
+
def punish(self, item):
|
|
122
|
+
self._dead_time[item] += 1
|
|
123
|
+
|
|
124
|
+
if self._dead_time[item] >= 3:
|
|
125
|
+
if item in self._active:
|
|
126
|
+
self._active.remove(item)
|
|
127
|
+
self._dead_time.pop(item, None)
|
|
128
|
+
|
|
129
|
+
def reward(self, item):
|
|
130
|
+
self._dead_time.pop(item, None)
|
|
131
|
+
|
|
132
|
+
def pick_best(self):
|
|
133
|
+
self._change_idx()
|
|
134
|
+
return self._active[self._next_idx]
|
|
135
|
+
|
|
136
|
+
def __len__(self):
|
|
137
|
+
return len(self._active)
|
|
138
|
+
|
|
139
|
+
def __bool__(self):
|
|
140
|
+
return bool(self._active)
|
|
141
|
+
|
|
142
|
+
def __iter__(self):
|
|
143
|
+
return self._active.__iter__()
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class RandomCache(RoundRobinCache):
|
|
147
|
+
def _change_idx(self):
|
|
148
|
+
# len(self._active) should be larger than 0 since pick-best only be called
|
|
149
|
+
# when bool(self) is true
|
|
150
|
+
self._next_idx = randint(0, len(self._active) - 1)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
CACHE_STRATEGY = {
|
|
154
|
+
'ranked': RankedCache,
|
|
155
|
+
'roundrobin': RoundRobinCache,
|
|
156
|
+
'random': RandomCache,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class ServiceDiscovery(ABC):
|
|
161
|
+
__ins__: Dict[str, 'ServiceDiscovery'] = {}
|
|
162
|
+
|
|
163
|
+
def __init__(self, **kwargs):
|
|
164
|
+
self.server_cache: Dict[str, AbstractServiceCache] = defaultdict(
|
|
165
|
+
CACHE_STRATEGY.get(OPTION.discovery.cache_strategy, RankedCache)
|
|
166
|
+
)
|
|
167
|
+
self.interval = 5
|
|
168
|
+
self._closed = None
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def closed(self):
|
|
172
|
+
if self._closed is None:
|
|
173
|
+
return True
|
|
174
|
+
return self._closed.is_set()
|
|
175
|
+
|
|
176
|
+
async def on_close(self):
|
|
177
|
+
pass
|
|
178
|
+
|
|
179
|
+
async def close(self):
|
|
180
|
+
logger.opt(lazy=True).debug('Closing service discovery ...')
|
|
181
|
+
if self._closed is not None:
|
|
182
|
+
self._closed.set()
|
|
183
|
+
await self.on_close()
|
|
184
|
+
|
|
185
|
+
async def init(self):
|
|
186
|
+
"""will block util close is called"""
|
|
187
|
+
if not self.closed:
|
|
188
|
+
logger.warning(f"{self.__class__.__name__} already running.")
|
|
189
|
+
return
|
|
190
|
+
|
|
191
|
+
self._closed = closed = asyncio.Event()
|
|
192
|
+
await self.on_startup()
|
|
193
|
+
|
|
194
|
+
async for _ in poll_event(closed, self.interval):
|
|
195
|
+
try:
|
|
196
|
+
await self.on_interval()
|
|
197
|
+
except Exception: # noqa
|
|
198
|
+
logger.exception('Exception occurs on interval.')
|
|
199
|
+
|
|
200
|
+
logger.opt(lazy=True).debug(f'{self.__class__.__name__} stopped.')
|
|
201
|
+
|
|
202
|
+
@abstractmethod
|
|
203
|
+
async def on_interval(self): pass
|
|
204
|
+
|
|
205
|
+
@abstractmethod
|
|
206
|
+
async def on_startup(self): pass
|
|
207
|
+
|
|
208
|
+
@abstractmethod
|
|
209
|
+
async def update_service_cache(self, server_name: str): pass
|
|
210
|
+
|
|
211
|
+
@abstractmethod
|
|
212
|
+
async def update_instance_cache(self, server_name: str): pass
|
|
213
|
+
|
|
214
|
+
def on_failure(self, server_name: str, addr):
|
|
215
|
+
self.server_cache[server_name].punish(addr)
|
|
216
|
+
|
|
217
|
+
def on_success(self, server_name: str, addr):
|
|
218
|
+
self.server_cache[server_name].reward(addr)
|
|
219
|
+
|
|
220
|
+
async def get_url(self, server_name: str, include_cb: bool = False):
|
|
221
|
+
if server_name not in self.server_cache:
|
|
222
|
+
await self.update_service_cache(server_name)
|
|
223
|
+
|
|
224
|
+
if server_name not in self.server_cache:
|
|
225
|
+
raise APIRequestError(f"Cannot find instance for server: {server_name}")
|
|
226
|
+
|
|
227
|
+
server_list = self.server_cache[server_name]
|
|
228
|
+
if not server_list:
|
|
229
|
+
await self.update_instance_cache(server_name)
|
|
230
|
+
|
|
231
|
+
if not server_list:
|
|
232
|
+
raise APIRequestError(f"Cannot find instance for server: {server_name}")
|
|
233
|
+
|
|
234
|
+
url = server_list.pick_best()
|
|
235
|
+
|
|
236
|
+
if include_cb:
|
|
237
|
+
return (
|
|
238
|
+
partial(self.on_success, server_name, url),
|
|
239
|
+
partial(self.on_failure, server_name, url),
|
|
240
|
+
url
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return url
|
|
244
|
+
|
|
245
|
+
def sync_get_url(self, server_name: str, include_cb: bool = False):
|
|
246
|
+
return evloop.run(self.get_url(server_name, include_cb))
|
|
247
|
+
|
|
248
|
+
@classmethod
|
|
249
|
+
def instantiate(cls):
|
|
250
|
+
impl = OPTION.discovery.implementation
|
|
251
|
+
|
|
252
|
+
if impl not in cls.__ins__:
|
|
253
|
+
if impl == 'eureka':
|
|
254
|
+
from deepfos.lib.eureka import Eureka
|
|
255
|
+
cls.__ins__[impl] = Eureka
|
|
256
|
+
elif impl == 'nacos':
|
|
257
|
+
from deepfos.lib.nacos import Nacos
|
|
258
|
+
cls.__ins__[impl] = Nacos
|
|
259
|
+
|
|
260
|
+
return cls.__ins__[impl]
|
|
261
|
+
|
|
262
|
+
@classmethod
|
|
263
|
+
async def start(cls):
|
|
264
|
+
await cls.instantiate().init()
|
|
265
|
+
await asyncio.sleep(0)
|
|
266
|
+
|
|
267
|
+
@classmethod
|
|
268
|
+
async def stop(cls):
|
|
269
|
+
for impl in cls.__ins__:
|
|
270
|
+
if cls.__ins__[impl].closed:
|
|
271
|
+
continue
|
|
272
|
+
|
|
273
|
+
await cls.__ins__[impl].close()
|