def run_values_server(name, zmq_context): session = Session() session.expire_on_commit = False vs = load_values_server(name, session) log.info("server loaded") start_values_server(vs, zmq_context, session) session.commit() log.info("server initialization complete") subscribe_to_all_feeds(vs) api_server = APIServer(ValuesServerAPI(vs), zmq_context, 9000) api_server.start() vs.feed_server_proxy.join_child_greenlets() session.close()
class FeedServerSpoof: def __init__(self, zmq_context): self.prices = [30, 31, 32, 33] self.sides = ['BID', 'ASK', 'LAST'] self.context = zmq_context self._create_pub_socket() self.current_subscriptions = {} def __call__(self): log.info("FeedServer initialized, starting API") self.api_server = APIServer(self, self.context, api_port='6011') self.api_server.start() while True: gevent.sleep() def _create_pub_socket(self, publish_port='6010'): socket = self.context.socket(zmq.PUB) endpoint = "tcp://*:{}".format(publish_port) socket.bind(endpoint) socket.setsockopt(zmq.SNDHWM, 500) self.outbound_socket = socket def subscribe_to_market_data(self, asset_id): log.info("subscription request for {} received".format(asset_id)) session = Session() asset_class_id = session.query(Asset.asset_class_id).filter(Asset.id==asset_id).one()[0] session.close() if not asset_id in self.current_subscriptions: gevent.spawn(self._spoof_feed, asset_id, asset_class_id) self.current_subscriptions[asset_id] = True def _spoof_feed(self, asset_id, asset_class_id): while True: gevent.sleep(3) log.info('sending spoofed update') self.outbound_socket.send(str(asset_id), zmq.SNDMORE) update = { 'asset_id': asset_id, 'price': self._get_price(asset_class_id), 'side': self._get_side(), 'qty': 10 } log.info(update) self.outbound_socket.send_json(update) def _get_side(self): return random.choice(sides) def _get_price(self, asset_class_id): return random.choice(prices[asset_class_id])
class FeedServer: def __init__(self, zmq_context): self.context = zmq_context self._create_pub_socket() self._create_sub_socket() self.current_subscriptions = {} def __call__(self): gevent.spawn(self._forward_updates) log.info("FeedServer initialized, starting API") self.api_server = APIServer(self, zmq_context, api_port='6011') self.api_server.start() while True: gevent.sleep() def subscribe_to_market_data(self, asset_id): log.info("subscription request for {} received".format(asset_id)) asset = self._lookup_asset(asset_id) if not asset_id in self.current_subscriptions: self.current_subscriptions[asset_id] = True self._request_data_from_gateways(asset) self._request_snapshot_from_gateways(asset) def _lookup_asset(self, asset_id): session = Session() asset = session.query(Asset)\ .filter(Asset.id == asset_id)\ .options(subqueryload_all(Asset.gateway_assets, GatewayAsset.gateway))\ .first() session.close() return asset def _request_data_from_gateways(self, asset): for ga in asset.gateway_assets: api_proxy = self._get_gateway_proxy(ga.gateway) self._send_subscribe_message(api_proxy, ga.gateway, asset.id) api_proxy.close() def _request_snapshot_from_gateways(self, asset): for ga in asset.gateway_assets: api_proxy = self._get_gateway_proxy(ga.gateway) self._request_snapshot(api_proxy, ga.gateway, asset.id) api_proxy.close() def _get_gateway_proxy(self, gateway): return APIProxy(self.context, api_url=gateway.ip_address, api_port=gateway.api_port) def _send_subscribe_message(self, api_proxy, gateway, asset_id): log.info("subscribing to feed from: {}".format(gateway.id)) subscribe_result = api_proxy.api_call('subscribe_to_market_data', {'asset_id': asset_id}) def _request_snapshot(self, api_proxy, gateway, asset_id): log.info("requesting MD snapshot from: {}".format(gateway.id)) snapshot_result = api_proxy.api_call('get_market_snapshot', {'asset_id': asset_id}) def _create_sub_socket(self): self._inbound_socket = self.context.socket(zmq.SUB) session = Session() gateways = session.query(Gateway).filter(Gateway.active == True).all() for g in gateways: self._inbound_socket.connect("{}:{}".format(g.ip_address, g.pub_port)) self._inbound_socket.setsockopt(zmq.SUBSCRIBE, '') def _create_pub_socket(self, publish_port='6010'): self._outbound_socket = self.context.socket(zmq.PUB) endpoint = "tcp://*:{}".format(publish_port) self._outbound_socket.bind(endpoint) self._outbound_socket.setsockopt(zmq.SNDHWM, 500) def _forward_updates(self): while True: msg = self._inbound_socket.recv_multipart() self._outbound_socket.send_multipart(msg) def shutdown(self): self._inbound_socket.close() self._outbound_socket.close() self.api_server.kill()