feat: refactoring progress
This commit is contained in:
@ -221,7 +221,7 @@ class Server(object):
|
|||||||
self.address = address
|
self.address = address
|
||||||
self.port = port
|
self.port = port
|
||||||
self.snapshot = ctx.socket(zmq.DEALER)
|
self.snapshot = ctx.socket(zmq.DEALER)
|
||||||
self.snapshot.linger = 0
|
self.snapshot = self.context.socket(zmq.DEALER)
|
||||||
self.snapshot.setsockopt(zmq.IDENTITY, id)
|
self.snapshot.setsockopt(zmq.IDENTITY, id)
|
||||||
self.snapshot.connect("tcp://{}:{}".format(address.decode(), port))
|
self.snapshot.connect("tcp://{}:{}".format(address.decode(), port))
|
||||||
self.subscriber = ctx.socket(zmq.SUB)
|
self.subscriber = ctx.socket(zmq.SUB)
|
||||||
|
112
replication.py
112
replication.py
@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
from .libs.dump_anything import dump_datablock
|
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
try:
|
try:
|
||||||
from .libs import umsgpack
|
from .libs import umsgpack
|
||||||
@ -19,13 +18,13 @@ class ReplicatedDataFactory(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.supported_types = []
|
self.supported_types = []
|
||||||
|
|
||||||
def register_type(dtype, implementation):
|
def register_type(self,dtype, implementation):
|
||||||
"""
|
"""
|
||||||
Register a new replicated datatype implementation
|
Register a new replicated datatype implementation
|
||||||
"""
|
"""
|
||||||
types.append((supported_types, implementation))
|
types.append((supported_types, implementation))
|
||||||
|
|
||||||
def match_type(data):
|
def match_type(self,data):
|
||||||
for stypes, implementation in self.supported_types:
|
for stypes, implementation in self.supported_types:
|
||||||
if isinstance(data, stypes):
|
if isinstance(data, stypes):
|
||||||
return implementation
|
return implementation
|
||||||
@ -33,8 +32,9 @@ class ReplicatedDataFactory(object):
|
|||||||
print("type not supported for replication")
|
print("type not supported for replication")
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def construct():
|
def construct(self,data):
|
||||||
return
|
implementation = self.match_type(data)
|
||||||
|
return implementation
|
||||||
|
|
||||||
class ReplicatedDatablock(object):
|
class ReplicatedDatablock(object):
|
||||||
"""
|
"""
|
||||||
@ -43,14 +43,13 @@ class ReplicatedDatablock(object):
|
|||||||
uuid = None # key (string)
|
uuid = None # key (string)
|
||||||
pointer = None # dcc data reference
|
pointer = None # dcc data reference
|
||||||
data = None # data blob (json)
|
data = None # data blob (json)
|
||||||
deps = None
|
deps = None # dependencies references
|
||||||
|
|
||||||
def __init__(self, owner=None, data=None):
|
def __init__(self, owner=None, data=None):
|
||||||
self.uuid = str(uuid4())
|
self.uuid = str(uuid4())
|
||||||
assert(owner)
|
assert(owner)
|
||||||
self.pointer = data
|
self.pointer = data
|
||||||
|
|
||||||
def load_serial(self):
|
|
||||||
|
|
||||||
def push(self, socket):
|
def push(self, socket):
|
||||||
"""
|
"""
|
||||||
@ -58,7 +57,12 @@ class ReplicatedDatablock(object):
|
|||||||
- serialize the data
|
- serialize the data
|
||||||
- send them as a multipart frame
|
- send them as a multipart frame
|
||||||
"""
|
"""
|
||||||
pass
|
data = self.serialize(self.pointer)
|
||||||
|
assert(isinstance(data, bytes))
|
||||||
|
|
||||||
|
key = self.uuid.encode()
|
||||||
|
|
||||||
|
socket.send_multipart([])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pull(cls, socket):
|
def pull(cls, socket):
|
||||||
@ -82,65 +86,65 @@ class ReplicatedDatablock(object):
|
|||||||
dict[self.uuid] = self
|
dict[self.uuid] = self
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def deserialize(self):
|
def deserialize(self,data):
|
||||||
"""
|
"""
|
||||||
I want to apply changes into the DCC
|
I want to apply changes into the DCC
|
||||||
|
|
||||||
|
MUST RETURN AN OBJECT INSTANCE
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self,data):
|
||||||
"""
|
"""
|
||||||
I want to load data from DCC
|
I want to load data from DCC
|
||||||
|
|
||||||
|
MUST RETURN A BYTE ARRAY
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
import bpy, mathutils
|
|
||||||
|
|
||||||
|
|
||||||
class BlenderTypesFactory():
|
# class RepObject(ReplicatedDatablock):
|
||||||
|
# def deserialize(self):
|
||||||
|
# try:
|
||||||
class RepObject(ReplicatedDatablock):
|
# if self.pointer is None:
|
||||||
def deserialize(self):
|
# pointer = None
|
||||||
try:
|
|
||||||
if self.pointer is None:
|
# # Object specific constructor...
|
||||||
pointer = None
|
# if self.data["data"] in bpy.data.meshes.keys():
|
||||||
|
# pointer = bpy.data.meshes[self.data["data"]]
|
||||||
# Object specific constructor...
|
# elif self.data["data"] in bpy.data.lights.keys():
|
||||||
if self.data["data"] in bpy.data.meshes.keys():
|
# pointer = bpy.data.lights[self.data["data"]]
|
||||||
pointer = bpy.data.meshes[self.data["data"]]
|
# elif self.data["data"] in bpy.data.cameras.keys():
|
||||||
elif self.data["data"] in bpy.data.lights.keys():
|
# pointer = bpy.data.cameras[self.data["data"]]
|
||||||
pointer = bpy.data.lights[self.data["data"]]
|
# elif self.data["data"] in bpy.data.curves.keys():
|
||||||
elif self.data["data"] in bpy.data.cameras.keys():
|
# pointer = bpy.data.curves[self.data["data"]]
|
||||||
pointer = bpy.data.cameras[self.data["data"]]
|
# elif self.data["data"] in bpy.data.armatures.keys():
|
||||||
elif self.data["data"] in bpy.data.curves.keys():
|
# pointer = bpy.data.armatures[self.data["data"]]
|
||||||
pointer = bpy.data.curves[self.data["data"]]
|
# elif self.data["data"] in bpy.data.grease_pencils.keys():
|
||||||
elif self.data["data"] in bpy.data.armatures.keys():
|
# pointer = bpy.data.grease_pencils[self.data["data"]]
|
||||||
pointer = bpy.data.armatures[self.data["data"]]
|
# elif self.data["data"] in bpy.data.curves.keys():
|
||||||
elif self.data["data"] in bpy.data.grease_pencils.keys():
|
# pointer = bpy.data.curves[self.data["data"]]
|
||||||
pointer = bpy.data.grease_pencils[self.data["data"]]
|
|
||||||
elif self.data["data"] in bpy.data.curves.keys():
|
# self.pointer = bpy.data.objects.new(self.data["name"], pointer)
|
||||||
pointer = bpy.data.curves[self.data["data"]]
|
|
||||||
|
# self.pointer.matrix_world = mathutils.Matrix(self.data["matrix_world"])
|
||||||
self.pointer = bpy.data.objects.new(self.data["name"], pointer)
|
|
||||||
|
# self.pointer.id = self.data['id']
|
||||||
self.pointer.matrix_world = mathutils.Matrix(self.data["matrix_world"])
|
|
||||||
|
# client = bpy.context.window_manager.session.username
|
||||||
self.pointer.id = self.data['id']
|
|
||||||
|
# if self.pointer.id == client or self.pointer.id == "Common":
|
||||||
client = bpy.context.window_manager.session.username
|
# self.pointer.hide_select = False
|
||||||
|
# else:
|
||||||
if self.pointer.id == client or self.pointer.id == "Common":
|
# self.pointer.hide_select = True
|
||||||
self.pointer.hide_select = False
|
|
||||||
else:
|
# except Exception as e:
|
||||||
self.pointer.hide_select = True
|
# logger.error("Object {} loading error: {} ".format(self.data["name"], e))
|
||||||
|
|
||||||
except Exception as e:
|
# def deserialize(self):
|
||||||
logger.error("Object {} loading error: {} ".format(self.data["name"], e))
|
# self.data = dump_datablock(self.pointer, 1)
|
||||||
|
|
||||||
def deserialize(self):
|
|
||||||
self.data = dump_datablock(self.pointer, 1)
|
|
||||||
|
|
||||||
|
|
||||||
|
67
replication_client.py
Normal file
67
replication_client.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import threading
|
||||||
|
import logging
|
||||||
|
import zmq
|
||||||
|
import time
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Client(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.rep_store = {}
|
||||||
|
self.net = ClientNetService(self.rep_store)
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.net.run()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.net.stop()
|
||||||
|
|
||||||
|
class ClientNetService(threading.Thread):
|
||||||
|
def __init__(self,store_reference=None):
|
||||||
|
# Threading
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.name = "NetLink"
|
||||||
|
self.daemon = True
|
||||||
|
self.exit_event = threading.Event()
|
||||||
|
|
||||||
|
# Networking
|
||||||
|
self.context = zmq.Context.instance()
|
||||||
|
|
||||||
|
self.snapshot = self.context.socket(zmq.DEALER)
|
||||||
|
self.snapshot.connect("tcp://127.0.0.1:5560")
|
||||||
|
|
||||||
|
self.subscriber = self.context.socket(zmq.SUB)
|
||||||
|
self.subscriber.setsockopt_string(zmq.SUBSCRIBE, '')
|
||||||
|
self.subscriber.connect("tcp://127.0.0.1:5561")
|
||||||
|
self.subscriber.linger = 0
|
||||||
|
|
||||||
|
self.publish = self.context.socket(zmq.PULL)
|
||||||
|
self.publish.bind("tcp://*:5562")
|
||||||
|
|
||||||
|
# For teststing purpose
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
log.debug("Running Net service")
|
||||||
|
|
||||||
|
poller = zmq.Poller()
|
||||||
|
poller.register(self.snapshot, zmq.POLLIN)
|
||||||
|
poller.register(self.subscriber, zmq.POLLIN)
|
||||||
|
poller.register(self.publish, zmq.POLLOUT)
|
||||||
|
|
||||||
|
while not self.exit_event.is_set():
|
||||||
|
items = dict(poller.poll(10))
|
||||||
|
|
||||||
|
if not items:
|
||||||
|
log.error("No request ")
|
||||||
|
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.exit_event.set()
|
||||||
|
|
||||||
|
#Wait the end of the run
|
||||||
|
while self.exit_event.is_set():
|
||||||
|
time.sleep(.1)
|
||||||
|
|
||||||
|
|
@ -1,16 +1,56 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import replication
|
from replication import ReplicatedDatablock, ReplicatedDataFactory
|
||||||
|
import umsgpack
|
||||||
|
import logging
|
||||||
|
from replication_client import Client
|
||||||
|
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class SampleData():
|
||||||
|
def __init__(self):
|
||||||
|
self.map = {
|
||||||
|
"sample":"data",
|
||||||
|
"sample":"data",
|
||||||
|
"sample":"data",
|
||||||
|
"sample":"data"
|
||||||
|
}
|
||||||
|
|
||||||
|
class RepSampleData(ReplicatedDatablock):
|
||||||
|
def serialize(self,data):
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
return pickle.dumps(data)
|
||||||
|
|
||||||
|
def deserialize(self,data):
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
return pickle.load(data)
|
||||||
|
|
||||||
class TestData(unittest.TestCase):
|
class TestData(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = {}
|
self.map = {}
|
||||||
self.sample_data = replication.ReplicatedDatablock(owner="toto")
|
|
||||||
|
self.client_api = Client()
|
||||||
|
def test_setup_data_factory(self):
|
||||||
|
factory = ReplicatedDataFactory()
|
||||||
|
factory.register_type(SampleData, RepSampleData)
|
||||||
|
|
||||||
|
def test_run_client(self):
|
||||||
|
self.client_api.connect()
|
||||||
|
|
||||||
|
def test_stop_client(self):
|
||||||
|
self.client_api.stop()
|
||||||
|
|
||||||
|
def test_add_replicated_value(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def test_create_replicated_data(self):
|
def test_create_replicated_data(self):
|
||||||
self.assertNotEqual(self.sample_data.uuid,None)
|
self.assertNotEqual(self.sample_data.uuid,None)
|
||||||
|
|
||||||
def test_push_replicated_data(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
Reference in New Issue
Block a user