feat: apply logic
feat: state draft
This commit is contained in:
128
replication.py
128
replication.py
@ -8,41 +8,54 @@ except:
|
||||
from libs import umsgpack
|
||||
|
||||
import zmq
|
||||
import pickle
|
||||
from enum import Enum
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
class RepState(Enum):
|
||||
ADDED = 0
|
||||
COMMITED = 1
|
||||
STAGED = 2
|
||||
|
||||
|
||||
class ReplicatedDataFactory(object):
|
||||
"""
|
||||
Manage the data types implamentations
|
||||
Manage the data types implementations
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.supported_types = []
|
||||
|
||||
def register_type(self,dtype, implementation):
|
||||
|
||||
# Default registered types
|
||||
self.register_type(str,RepCommand)
|
||||
|
||||
def register_type(self, dtype, implementation):
|
||||
"""
|
||||
Register a new replicated datatype implementation
|
||||
"""
|
||||
self.supported_types.append((dtype, implementation))
|
||||
|
||||
def match_type_by_instance(self,data):
|
||||
def match_type_by_instance(self, data):
|
||||
"""
|
||||
Find corresponding type to the given datablock
|
||||
"""
|
||||
for stypes, implementation in self.supported_types:
|
||||
for stypes, implementation in self.supported_types:
|
||||
if isinstance(data, stypes):
|
||||
return implementation
|
||||
|
||||
|
||||
print("type not supported for replication")
|
||||
raise NotImplementedError
|
||||
|
||||
def match_type_by_name(self,type_name):
|
||||
for stypes, implementation in self.supported_types:
|
||||
if type_name == stypes.__name__:
|
||||
def match_type_by_name(self, type_name):
|
||||
for stypes, implementation in self.supported_types:
|
||||
if type_name == implementation.__name__:
|
||||
return implementation
|
||||
|
||||
return None
|
||||
print("type not supported for replication")
|
||||
raise NotImplementedError
|
||||
|
||||
def construct_from_dcc(self,data):
|
||||
def construct_from_dcc(self, data):
|
||||
implementation = self.match_type_by_instance(data)
|
||||
return implementation
|
||||
|
||||
@ -52,24 +65,26 @@ class ReplicatedDataFactory(object):
|
||||
"""
|
||||
return self.match_type_by_name(type_name)
|
||||
|
||||
|
||||
class ReplicatedDatablock(object):
|
||||
"""
|
||||
Datablock used for replication
|
||||
"""
|
||||
uuid = None # key (string)
|
||||
pointer = None # dcc data reference
|
||||
data = None # data blob (json)
|
||||
str_type = None # data type name (for deserialization)
|
||||
deps = None # dependencies references
|
||||
owner = None
|
||||
uuid = None # uuid used as key (string)
|
||||
pointer = None # dcc data ref (DCC type)
|
||||
buffer = None # data blob (json)
|
||||
str_type = None # data type name (string)
|
||||
deps = [None] # dependencies array (string)
|
||||
owner = None # Data owner (string)
|
||||
state = None # Data state (RepState)
|
||||
|
||||
def __init__(self, owner=None, data=None, uuid=None):
|
||||
def __init__(self, owner=None, data=None, uuid=None, buffer=None):
|
||||
self.uuid = uuid if uuid else str(uuid4())
|
||||
assert(owner)
|
||||
self.owner = owner
|
||||
self.pointer = data
|
||||
self.str_type = type(data).__name__
|
||||
|
||||
self.buffer = buffer if buffer else None
|
||||
self.str_type = type(self).__name__
|
||||
|
||||
def push(self, socket):
|
||||
"""
|
||||
@ -83,8 +98,8 @@ class ReplicatedDatablock(object):
|
||||
key = self.uuid.encode()
|
||||
type = self.str_type.encode()
|
||||
|
||||
socket.send_multipart([key,owner,type,data])
|
||||
|
||||
socket.send_multipart([key, owner, type, data])
|
||||
|
||||
@classmethod
|
||||
def pull(cls, socket, factory):
|
||||
"""
|
||||
@ -92,59 +107,86 @@ class ReplicatedDatablock(object):
|
||||
- read data from the socket
|
||||
- reconstruct an instance
|
||||
"""
|
||||
uuid, owner,str_type, data = socket.recv_multipart(zmq.NOBLOCK)
|
||||
|
||||
uuid, owner, str_type, data = socket.recv_multipart(zmq.NOBLOCK)
|
||||
|
||||
str_type = str_type.decode()
|
||||
owner=owner.decode()
|
||||
uuid=uuid.decode()
|
||||
owner = owner.decode()
|
||||
uuid = uuid.decode()
|
||||
data = self.deserialize(data)
|
||||
|
||||
instance = factory.construct_from_net(str_type)(owner=owner, uuid=uuid)
|
||||
instance = factory.construct_from_net(str_type)(owner=owner, uuid=uuid, buffer=data)
|
||||
|
||||
# instance.data = instance.deserialize(data)
|
||||
return instance
|
||||
|
||||
|
||||
def store(self, dict, persistent=False):
|
||||
def store(self, dict, persistent=False):
|
||||
"""
|
||||
I want to store my replicated data. Persistent means into the disk
|
||||
If uuid is none we delete the key from the volume
|
||||
"""
|
||||
if self.uuid is not None:
|
||||
if self.data == 'None':
|
||||
logger.info("erasing key {}".format(self.uuid))
|
||||
if self.buffer == 'None':
|
||||
logger.debug("erasing key {}".format(self.uuid))
|
||||
del dict[self.uuid]
|
||||
else:
|
||||
dict[self.uuid] = self
|
||||
|
||||
|
||||
return self.uuid
|
||||
|
||||
def deserialize(self,data):
|
||||
def deserialize(self, data):
|
||||
"""
|
||||
I want to apply changes into the DCC
|
||||
|
||||
MUST RETURN AN OBJECT INSTANCE
|
||||
BUFFER -> JSON
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def serialize(self,data):
|
||||
|
||||
|
||||
def serialize(self, data):
|
||||
"""
|
||||
I want to load data from DCC
|
||||
|
||||
DCC -> JSON
|
||||
|
||||
MUST RETURN A BYTE ARRAY
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def apply(self,data,target):
|
||||
"""
|
||||
JSON -> DCC
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def resolve(self):
|
||||
"""
|
||||
I want to resolve my orphan data to an existing one
|
||||
= Assing my pointer
|
||||
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
def dump(self):
|
||||
return self.deserialize(self.buffer)
|
||||
|
||||
class RepCommand(ReplicatedDatablock):
|
||||
|
||||
def serialize(self,data):
|
||||
return pickle.dumps(data)
|
||||
|
||||
def deserialize(self,data):
|
||||
return pickle.load(data)
|
||||
|
||||
def apply(self,data,target):
|
||||
target = data
|
||||
|
||||
# class RepObject(ReplicatedDatablock):
|
||||
# def deserialize(self):
|
||||
# try:
|
||||
# if self.pointer is None:
|
||||
# pointer = None
|
||||
|
||||
|
||||
# # Object specific constructor...
|
||||
# if self.data["data"] in bpy.data.meshes.keys():
|
||||
# pointer = bpy.data.meshes[self.data["data"]]
|
||||
@ -173,11 +215,9 @@ class ReplicatedDatablock(object):
|
||||
# self.pointer.hide_select = False
|
||||
# else:
|
||||
# self.pointer.hide_select = True
|
||||
|
||||
|
||||
# except Exception as e:
|
||||
# logger.error("Object {} loading error: {} ".format(self.data["name"], e))
|
||||
|
||||
# def deserialize(self):
|
||||
# self.data = dump_datablock(self.pointer, 1)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user