def setUp(self): super(StateTest, self).setUp() self.project_id = 'test' self.namespace = 'test' self.channel = 'test' self.uid_1 = 'test-1' self.uid_2 = 'test-2' self.user_id = 'test' self.user_id_extra = 'test_extra' self.user_info = 'test user info' self.message_1 = json.dumps('test message 1') self.message_2 = json.dumps('test message 2') self.message_3 = json.dumps('test message 3') self.state = State(io_loop=self.io_loop, history_size=2, presence_timeout=1) self.state.connect()
def main(): tornado.options.parse_command_line() try: custom_settings = json.load(open(options.config, 'r')) except IOError: logger.warning( "Application started without configuration file.\n" "This is normal only during development and if you\n" "want to use MongoDB as data storage.\n" ) custom_settings = {} database_settings = custom_settings.get('storage', {}) # detect and apply database storage module storage_module = database_settings.get( 'module', 'centrifuge.storage.mongodb' ) storage = utils.import_module(storage_module) ioloop_instance = tornado.ioloop.IOLoop.instance() settings = dict( cookie_secret=custom_settings.get("cookie_secret", "bad secret"), login_url="/auth", template_path=os.path.join( os.path.dirname(__file__), os.path.join("web/frontend", "templates") ), static_path=os.path.join( os.path.dirname(__file__), os.path.join("web/frontend", "static") ), xsrf_cookies=True, autoescape="xhtml_escape", debug=options.debug, options=custom_settings ) try: app = Application(settings) server = tornado.httpserver.HTTPServer(app) server.listen(options.port) except Exception as e: return stop_running(str(e)) # create unique uid for this application app.uid = uuid.uuid4().hex state = State(app) centrifuge.handlers.state = state centrifuge.web.handlers.state = state centrifuge.rpc.state = state state.set_storage(storage) def run_periodic_state_update(): state.update() periodic_state_update = tornado.ioloop.PeriodicCallback( state.update, custom_settings.get('state_update_interval', 30000) ) periodic_state_update.start() ioloop_instance.add_callback( functools.partial( storage.init_db, state, database_settings.get('settings', {}), run_periodic_state_update ) ) app.zmq_pub_sub_proxy = options.zmq_pub_sub_proxy context = zmq.Context() # create PUB socket to publish instance events into it publish_socket = context.socket(zmq.PUB) # do not try to send messages after closing publish_socket.setsockopt(zmq.LINGER, 0) if app.zmq_pub_sub_proxy: # application started with XPUB/XSUB proxy app.zmq_xsub = options.zmq_xsub publish_socket.connect(app.zmq_xsub) else: # application started without XPUB/XSUB proxy if options.zmq_pub_port_shift: # calculate zmq pub port number zmq_pub_port = options.port + options.zmq_pub_port_shift else: zmq_pub_port = options.zmq_pub_port app.zmq_pub_port = zmq_pub_port publish_socket.bind( "tcp://%s:%s" % (options.zmq_pub_listen, str(app.zmq_pub_port)) ) # wrap pub socket into ZeroMQ stream app.pub_stream = ZMQStream(publish_socket) # create SUB socket listening to all events from all app instances subscribe_socket = context.socket(zmq.SUB) if app.zmq_pub_sub_proxy: # application started with XPUB/XSUB proxy app.zmq_xpub = options.zmq_xpub subscribe_socket.connect(app.zmq_xpub) else: # application started without XPUB/XSUB proxy app.zmq_sub_address = options.zmq_sub_address for address in app.zmq_sub_address: subscribe_socket.connect(address) subscribe_socket.setsockopt_string( zmq.SUBSCRIBE, six.u(create_control_channel_name()) ) def listen_control_channel(): # wrap sub socket into ZeroMQ stream and set its on_recv callback app.sub_stream = ZMQStream(subscribe_socket) handle = functools.partial(handle_control_message, app) app.sub_stream.on_recv(handle) ioloop_instance.add_callback(listen_control_channel) app.event_callbacks = [] callbacks = custom_settings.get('event_callbacks', []) for callback in callbacks: event_callback = utils.namedAny(callback) app.event_callbacks.append(event_callback) if not hasattr(app, 'admin_connections'): # initialize dict to keep admin connections app.admin_connections = {} if not hasattr(app, 'connections'): # initialize dict to keep client's connections app.connections = {} if not hasattr(app, 'back_off'): # initialize dict to keep back-off information for projects app.back_off = {} logger.info("Application started") logger.info("Tornado port: {0}".format(options.port)) if app.zmq_pub_sub_proxy: logger.info( "ZeroMQ XPUB: {0}, XSUB: {1}".format( app.zmq_xpub, app.zmq_xsub, ) ) else: logger.info( "ZeroMQ PUB - {0}; subscribed to {1}".format( app.zmq_pub_port, app.zmq_sub_address ) ) logger.info("Storage module: {0}".format(storage_module)) # finally, let's go try: ioloop_instance.start() except KeyboardInterrupt: logger.info('interrupted') finally: # clean if hasattr(app, 'pub_stream'): app.pub_stream.close() if hasattr(app, 'sub_stream'): app.sub_stream.on_recv(None) app.sub_stream.close()
class StateTest(AsyncTestCase): """ Test the client """ def setUp(self): super(StateTest, self).setUp() self.project_id = 'test' self.namespace = 'test' self.channel = 'test' self.uid_1 = 'test-1' self.uid_2 = 'test-2' self.user_id = 'test' self.user_id_extra = 'test_extra' self.user_info = 'test user info' self.message_1 = json.dumps('test message 1') self.message_2 = json.dumps('test message 2') self.message_3 = json.dumps('test message 3') self.state = State(io_loop=self.io_loop, history_size=2, presence_timeout=1) self.state.connect() @gen_test def test_presence(self): result = yield Task(self.state.client.flushdb) self.assertEqual(result, "OK") result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertEqual(result, {}) result, error = yield self.state.add_presence(self.project_id, self.namespace, self.channel, self.uid_1, self.user_info) self.assertEqual(result, True) result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertTrue(self.uid_1 in result) result, error = yield self.state.add_presence(self.project_id, self.namespace, self.channel, self.uid_1, self.user_info) self.assertEqual(result, True) result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertTrue(self.uid_1 in result) self.assertEqual(len(result), 1) result, error = yield self.state.add_presence(self.project_id, self.namespace, self.channel, self.uid_2, self.user_info) self.assertEqual(result, True) result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertTrue(self.uid_1 in result) self.assertTrue(self.uid_2 in result) self.assertEqual(len(result), 2) result, error = yield self.state.remove_presence( self.project_id, self.namespace, self.channel, self.uid_2) self.assertEqual(result, True) result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertTrue(self.uid_1 in result) self.assertTrue(self.uid_2 not in result) self.assertEqual(len(result), 1) time.sleep(2) result, error = yield self.state.get_presence(self.project_id, self.namespace, self.channel) self.assertEqual(result, {}) @gen_test def test_history(self): result = yield Task(self.state.client.flushdb) self.assertEqual(result, "OK") result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_1) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history(self.project_id, self.namespace, self.channel) self.assertEqual(error, None) self.assertEqual(len(result), 1) result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_2) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history(self.project_id, self.namespace, self.channel) self.assertEqual(error, None) self.assertEqual(len(result), 2) result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_3) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history(self.project_id, self.namespace, self.channel) self.assertEqual(error, None) self.assertEqual(len(result), 2)
class StateTest(AsyncTestCase): """ Test the client """ def setUp(self): super(StateTest, self).setUp() self.project_id = 'test' self.namespace = 'test' self.channel = 'test' self.uid_1 = 'test-1' self.uid_2 = 'test-2' self.user_id = 'test' self.user_id_extra = 'test_extra' self.user_info = 'test user info' self.message_1 = json.dumps('test message 1') self.message_2 = json.dumps('test message 2') self.message_3 = json.dumps('test message 3') self.state = State(io_loop=self.io_loop, history_size=2, presence_timeout=1) self.state.connect() @gen_test def test_presence(self): result = yield Task(self.state.client.flushdb) self.assertEqual(result, "OK") result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertEqual(result, {}) result, error = yield self.state.add_presence( self.project_id, self.namespace, self.channel, self.uid_1, self.user_info ) self.assertEqual(result, True) result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertTrue(self.uid_1 in result) result, error = yield self.state.add_presence( self.project_id, self.namespace, self.channel, self.uid_1, self.user_info ) self.assertEqual(result, True) result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertTrue(self.uid_1 in result) self.assertEqual(len(result), 1) result, error = yield self.state.add_presence( self.project_id, self.namespace, self.channel, self.uid_2, self.user_info ) self.assertEqual(result, True) result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertTrue(self.uid_1 in result) self.assertTrue(self.uid_2 in result) self.assertEqual(len(result), 2) result, error = yield self.state.remove_presence( self.project_id, self.namespace, self.channel, self.uid_2 ) self.assertEqual(result, True) result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertTrue(self.uid_1 in result) self.assertTrue(self.uid_2 not in result) self.assertEqual(len(result), 1) time.sleep(2) result, error = yield self.state.get_presence( self.project_id, self.namespace, self.channel ) self.assertEqual(result, {}) @gen_test def test_history(self): result = yield Task(self.state.client.flushdb) self.assertEqual(result, "OK") result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_1 ) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history( self.project_id, self.namespace, self.channel ) self.assertEqual(error, None) self.assertEqual(len(result), 1) result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_2 ) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history( self.project_id, self.namespace, self.channel ) self.assertEqual(error, None) self.assertEqual(len(result), 2) result, error = yield self.state.add_history_message( self.project_id, self.namespace, self.channel, self.message_3 ) self.assertEqual(error, None) self.assertEqual(result, True) result, error = yield self.state.get_history( self.project_id, self.namespace, self.channel ) self.assertEqual(error, None) self.assertEqual(len(result), 2)
def main(): tornado.options.parse_command_line() try: custom_settings = json.load(open(options.config, "r")) except IOError: logger.warning( "Application started without configuration file.\n" "This is normal only during development and if you\n" "want to use MongoDB as data storage.\n" ) custom_settings = {} database_settings = custom_settings.get("storage", {}) # detect and apply database storage module storage_module = database_settings.get("module", "centrifuge.storage.mongodb") storage = utils.import_module(storage_module) ioloop_instance = tornado.ioloop.IOLoop.instance() settings = dict( cookie_secret=custom_settings.get("cookie_secret", "bad secret"), login_url="/auth", template_path=os.path.join(os.path.dirname(__file__), os.path.join("web/frontend", "templates")), static_path=os.path.join(os.path.dirname(__file__), os.path.join("web/frontend", "static")), xsrf_cookies=True, autoescape="xhtml_escape", debug=options.debug, options=custom_settings, ) try: app = Application(settings) server = tornado.httpserver.HTTPServer(app) server.listen(options.port) except Exception as e: return stop_running(str(e)) # create unique uid for this application app.uid = uuid.uuid4().hex state = State(app) centrifuge.handlers.state = state centrifuge.web.handlers.state = state centrifuge.rpc.state = state state.set_storage(storage) def run_periodic_state_update(): state.update() periodic_state_update = tornado.ioloop.PeriodicCallback( state.update, custom_settings.get("state_update_interval", 30000) ) periodic_state_update.start() ioloop_instance.add_callback( functools.partial(storage.init_db, state, database_settings.get("settings", {}), run_periodic_state_update) ) app.zmq_pub_sub_proxy = options.zmq_pub_sub_proxy context = zmq.Context() # create PUB socket to publish instance events into it publish_socket = context.socket(zmq.PUB) # do not try to send messages after closing publish_socket.setsockopt(zmq.LINGER, 0) if app.zmq_pub_sub_proxy: # application started with XPUB/XSUB proxy app.zmq_xsub = options.zmq_xsub publish_socket.connect(app.zmq_xsub) else: # application started without XPUB/XSUB proxy if options.zmq_pub_port_shift: # calculate zmq pub port number zmq_pub_port = options.port + options.zmq_pub_port_shift else: zmq_pub_port = options.zmq_pub_port app.zmq_pub_port = zmq_pub_port publish_socket.bind("tcp://%s:%s" % (options.zmq_pub_listen, str(app.zmq_pub_port))) # wrap pub socket into ZeroMQ stream app.pub_stream = ZMQStream(publish_socket) # create SUB socket listening to all events from all app instances subscribe_socket = context.socket(zmq.SUB) if app.zmq_pub_sub_proxy: # application started with XPUB/XSUB proxy app.zmq_xpub = options.zmq_xpub subscribe_socket.connect(app.zmq_xpub) else: # application started without XPUB/XSUB proxy app.zmq_sub_address = options.zmq_sub_address for address in app.zmq_sub_address: subscribe_socket.connect(address) subscribe_socket.setsockopt_string(zmq.SUBSCRIBE, six.u(create_control_channel_name())) def listen_control_channel(): # wrap sub socket into ZeroMQ stream and set its on_recv callback app.sub_stream = ZMQStream(subscribe_socket) handle = functools.partial(handle_control_message, app) app.sub_stream.on_recv(handle) ioloop_instance.add_callback(listen_control_channel) app.event_callbacks = [] callbacks = custom_settings.get("event_callbacks", []) for callback in callbacks: event_callback = utils.namedAny(callback) app.event_callbacks.append(event_callback) if not hasattr(app, "admin_connections"): # initialize dict to keep admin connections app.admin_connections = {} if not hasattr(app, "connections"): # initialize dict to keep client's connections app.connections = {} if not hasattr(app, "back_off"): # initialize dict to keep back-off information for projects app.back_off = {} logger.info("Application started") logger.info("Tornado port: {0}".format(options.port)) if app.zmq_pub_sub_proxy: logger.info("ZeroMQ XPUB: {0}, XSUB: {1}".format(app.zmq_xpub, app.zmq_xsub)) else: logger.info("ZeroMQ PUB - {0}; subscribed to {1}".format(app.zmq_pub_port, app.zmq_sub_address)) logger.info("Storage module: {0}".format(storage_module)) # finally, let's go try: ioloop_instance.start() except KeyboardInterrupt: logger.info("interrupted") finally: # clean if hasattr(app, "pub_stream"): app.pub_stream.close() if hasattr(app, "sub_stream"): app.sub_stream.on_recv(None) app.sub_stream.close()