Пример #1
0
 def publish_stopped(session, stop_details):
     self.log.info(
         "stopped component: {session} id={session_id}",
         session=class_name(session),
         session_id=session._session_id,
     )
     topic = self._uri_prefix + '.on_component_stop'
     event = {u'id': id}
     caller = details.caller if details else None
     self.publish(topic, event, options=PublishOptions(exclude=caller))
     return event
Пример #2
0
    def add_pythonpath(self, paths, prepend=True, details=None):
        """
      Add paths to Python module search paths.

      :param paths: List of paths. Relative paths will be resolved relative
                    to the node directory.
      :type paths: list
      :param prepend: If `True`, prepend the given paths to the current paths.
                      Otherwise append.
      :type prepend: bool
      """
        if self.debug:
            log.msg("{}.add_pythonpath".format(self.__class__.__name__))

        paths_added = []
        for p in paths:
            ## transform all paths (relative to cbdir) into absolute paths
            ##
            path_to_add = os.path.abspath(
                os.path.join(self.config.extra.cbdir, p))
            if os.path.isdir(path_to_add):
                paths_added.append({'requested': p, 'resolved': path_to_add})
            else:
                emsg = "ERROR: cannot add Python search path '{}' - resolved path '{}' is not a directory".format(
                    p, path_to_add)
                log.msg(emsg)
                raise ApplicationError('crossbar.error.invalid_argument',
                                       emsg,
                                       requested=p,
                                       resolved=path_to_add)

        ## now extend python module search path
        ##
        paths_added_resolved = [p['resolved'] for p in paths_added]
        if prepend:
            sys.path = paths_added_resolved + sys.path
        else:
            sys.path.extend(paths_added_resolved)

        ## publish event "on_pythonpath_add" to all but the caller
        ##
        topic = 'crossbar.node.{}.worker.{}.on_pythonpath_add'.format(
            self.config.extra.node, self.config.extra.worker)
        res = {
            'paths': sys.path,
            'paths_added': paths_added,
            'prepend': prepend,
            'who': details.authid
        }
        self.publish(topic,
                     res,
                     options=PublishOptions(exclude=[details.caller]))

        return res
Пример #3
0
def do_publish(reactor, session, options):
    publish_args = list(options.publish_args)
    publish_kwargs = {} if options.keyword is None else {
        k: v
        for k, v in options.keyword
    }

    yield session.publish(options.uri,
                          *publish_args,
                          options=PublishOptions(acknowledge=True),
                          **publish_kwargs)
Пример #4
0
    def stop_component(self, component_id, details=None):
        """
        Stop a component currently running within this container.

        :param component_id: The ID of the component to stop.
        :type component_id: int

        :param details: Caller details.
        :type details: instance of :class:`autobahn.wamp.types.CallDetails`

        :returns: Stop information.
        :rtype: dict
        """
        self.log.debug('{klass}.stop_component({component_id}, {details})',
                       klass=self.__class__.__name__,
                       component_id=component_id,
                       details=details)

        if component_id not in self.components:
            raise ApplicationError(
                u'crossbar.error.no_such_object',
                'no component with ID {} running in this container'.format(
                    component_id))

        component = self.components[component_id]

        try:
            component.proto.close()
        except:
            self.log.failure(
                "failed to close protocol on component '{component_id}': {log_failure}",
                component_id=component_id)
            raise
        else:
            # essentially just waiting for "on_component_stop"
            yield component._stopped

        stopped = {
            u'component_id': component_id,
            u'uptime': (datetime.utcnow() - component.started).total_seconds(),
            u'caller': {
                u'session': details.caller,
                u'authid': details.caller_authid,
                u'authrole': details.caller_authrole,
            }
        }

        del self.components[component_id]

        self.publish(u'{}.on_component_stopped'.format(self._uri_prefix),
                     stopped,
                     options=PublishOptions(exclude=details.caller))

        returnValue(stopped)
Пример #5
0
    def add_pythonpath(self, paths, prepend=True, details=None):
        """
        Add paths to Python module search paths.

        This procedure is registered under WAMP URI
        ``crossbar.worker.<worker_id>.add_pythonpath``.

        :param paths: List of paths. Relative paths will be resolved relative
                      to the node directory.
        :type paths: list[str]
        :param prepend: If `True`, prepend the given paths to the current paths.
                        Otherwise append.
        :type prepend: bool
        """
        self.log.debug("{klass}.add_pythonpath", klass=self.__class__.__name__)

        paths_added = []
        for p in paths:
            # transform all paths (relative to cbdir) into absolute paths
            #
            path_to_add = os.path.abspath(os.path.join(self.config.extra.cbdir, p))
            if os.path.isdir(path_to_add):
                paths_added.append({'requested': p, 'resolved': path_to_add})
            else:
                emsg = "Cannot add Python search path '{}': resolved path '{}' is not a directory".format(
                    p, path_to_add)
                self.log.error(emsg)
                raise ApplicationError('crossbar.error.invalid_argument', emsg, requested=p, resolved=path_to_add)

        # now extend python module search path
        #
        paths_added_resolved = [p['resolved'] for p in paths_added]
        if prepend:
            sys.path = paths_added_resolved + sys.path
        else:
            sys.path.extend(paths_added_resolved)

        # "It is important to note that the global working_set object is initialized from
        # sys.path when pkg_resources is first imported, but is only updated if you do all
        # future sys.path manipulation via pkg_resources APIs. If you manually modify sys.path,
        # you must invoke the appropriate methods on the working_set instance to keep it in sync."
        #
        # @see: https://pythonhosted.org/setuptools/pkg_resources.html#workingset-objects
        #
        for p in paths_added_resolved:
            pkg_resources.working_set.add_entry(p)

        # publish event "on_pythonpath_add" to all but the caller
        #
        topic = '{}.on_pythonpath_add'.format(self._uri_prefix)
        res = {'paths': sys.path, 'paths_added': paths_added, 'prepend': prepend, 'who': details.caller}
        self.publish(topic, res, options=PublishOptions(exclude=details.caller))

        return res
Пример #6
0
    def onJoin(self, details):
        print("session attached {}".format(details))

        for topic in [u"com.example.history", u"com.example.no_history_here"]:
            print("publishing '{}' as retained event".format(topic))
            pub = yield self.publish(
                topic,
                "some data, topic was '{}'".format(topic),
                options=PublishOptions(retain=True, acknowledge=True),
            )
            print("published: {}".format(pub))
Пример #7
0
    def set_cpu_affinity(self, cpus, details=None):
        """
        Set CPU affinity of this process.

        **Usage:**

        This procedure is registered under

        * ``crossbar.worker.<worker_id>.set_cpu_affinity``

        **Errors:**

        The procedure may raise the following errors:

        * ``crossbar.error.feature_unavailable`` - the required support packages are not installed

        **Events:**

        When the CPU affinity has been successfully set, an event is published to

        * ``crossbar.node.{}.worker.{}.on_cpu_affinity_set``

        :param cpus: List of CPU IDs to set process affinity to. Each CPU ID must be
            from the list `[0 .. N_CPUs]`, where N_CPUs can be retrieved via
            ``crossbar.worker.<worker_id>.get_cpu_count``.
        :type cpus: list of int
        """
        if not _HAS_PSUTIL:
            emsg = "Unable to set CPU affinity: required package 'psutil' is not installed"
            self.log.warn(emsg)
            raise ApplicationError(u"crossbar.error.feature_unavailable", emsg)

        try:
            p = psutil.Process(os.getpid())
            p.cpu_affinity(cpus)
            new_affinity = p.cpu_affinity()
        except Exception as e:
            emsg = "Could not set CPU affinity: {}".format(e)
            self.log.failure(emsg)
            raise ApplicationError(u"crossbar.error.runtime_error", emsg)
        else:

            # publish info to all but the caller ..
            #
            cpu_affinity_set_topic = u'{}.on_cpu_affinity_set'.format(self._uri_prefix)
            cpu_affinity_set_info = {
                u'affinity': new_affinity,
                u'who': details.caller
            }
            self.publish(cpu_affinity_set_topic, cpu_affinity_set_info, options=PublishOptions(exclude=details.caller))

            # .. and return info directly to caller
            #
            return new_affinity
Пример #8
0
   def onJoin(self, details):
      print("Client session joined: {}".format(details))

      ## call a procedure we are allowed to call (so this should succeed)
      ##
      try:
         res = yield self.call(u'com.example.add2', 2, 3)
         print("call result: {}".format(res))
      except Exception as e:
         print("call error: {}".format(e))

      ## (try to) register a procedure where we are not allowed to (so this should fail)
      ##
      try:
         reg = yield self.register(lambda x, y: x * y, u'com.example.mul2')
      except Exception as e:
         print("registration failed (this is expected!) {}".format(e))

      ## publish to a couple of topics we are allowed to publish to.
      ##
      for topic in [
         u'com.example.topic1',
         u'com.foobar.topic1']:
         try:
            yield self.publish(topic, "hello", options = PublishOptions(acknowledge = True))
            print("ok, event published to topic {}".format(topic))
         except Exception as e:
            print("publication to topic {} failed: {}".format(topic, e))

      ## (try to) publish to a couple of topics we are not allowed to publish to (so this should fail)
      ##
      for topic in [
         u'com.example.topic2',
         u'com.foobar.topic2']:
         try:
            yield self.publish(topic, "hello", options = PublishOptions(acknowledge = True))
            print("ok, event published to topic {}".format(topic))
         except Exception as e:
            print("publication to topic {} failed (this is expected!) {}".format(topic, e))

      self.leave()
Пример #9
0
 def on_data(self, changed, last):
     """
     Hook that fires when xbox controller has emitted some data.
     """
     self.publish(u'{}.on_data'.format(self._prefix),
                  last,
                  changed,
                  options=PublishOptions(retain=True))
     self.log.info(
         "on_data event published: last={last}, changed={changed}",
         changed=changed,
         last=last)
Пример #10
0
 def on_event(*args, **kwargs):
     details = kwargs.pop('details')
     # FIXME: setup things so out (the node's) identity gets disclosed
     self.publish(uri, *args, options=PublishOptions(), **kwargs)
     self.log.info(
         "forwarded from {other} event to {me} ({dir}): args={args}, details={details}",
         other=other,
         me=self,
         dir=self._DIR,
         args=args,
         details=details,
     )
Пример #11
0
        def square(val, details=None):
            print("square called from: {}".format(details.caller))

            if val < 0:
                self.publish(u'com.myapp.square_on_nonpositive', val)
            elif val == 0:
                if details.caller:
                    options = PublishOptions(exclude=[details.caller])
                else:
                    options = None
                self.publish(u'com.myapp.square_on_nonpositive', val, options=options)
            return val * val
Пример #12
0
    def restart_component(self,
                          component_id,
                          reload_modules=False,
                          details=None):
        """
        Restart a component currently running within this container using the
        same configuration that was used when first starting the component.

        :param component_id: The ID of the component to restart.
        :type component_id: str

        :param reload_modules: If `True`, enforce reloading of modules (user code)
                               that were modified (see: TrackingModuleReloader).
        :type reload_modules: bool

        :param details: Caller details.
        :type details: instance of :class:`autobahn.wamp.types.CallDetails`

        :returns dict -- A dict with combined info from component stopping/starting.
        """
        if component_id not in self.components:
            raise ApplicationError(
                u'crossbar.error.no_such_object',
                'no component with ID {} running in this container'.format(
                    component_id))

        component = self.components[component_id]

        stopped = yield self.stop_container_component(component_id,
                                                      details=details)
        started = yield self.start_component(component_id,
                                             component.config,
                                             reload_modules=reload_modules,
                                             details=details)

        del stopped[u'caller']
        del started[u'caller']

        restarted = {
            u'stopped': stopped,
            u'started': started,
            u'caller': {
                u'session': details.caller,
                u'authid': details.caller_authid,
                u'authrole': details.caller_authrole,
            }
        }

        self.publish(u'{}.on_component_restarted'.format(self._uri_prefix),
                     restarted,
                     options=PublishOptions(exclude=details.caller))

        returnValue(restarted)
Пример #13
0
    def start_router_realm_role(self,
                                realm_id,
                                role_id,
                                role_config,
                                details=None):
        """
        Start a role on a realm running on this router worker.

        :param id: The ID of the realm the role should be started on.
        :type id: str

        :param role_id: The ID of the role to start under.
        :type role_id: str

        :param config: The role configuration.
        :type config: dict

        :param details: Call details.
        :type details: :class:`autobahn.wamp.types.CallDetails`
        """
        self.log.info(
            'Starting role "{role_id}" on realm "{realm_id}" {method}',
            role_id=role_id,
            realm_id=realm_id,
            method=hltype(self.start_router_realm_role))

        if realm_id not in self.realms:
            raise ApplicationError(u"crossbar.error.no_such_object",
                                   "No realm with ID '{}'".format(realm_id))

        if role_id in self.realms[realm_id].roles:
            raise ApplicationError(
                u"crossbar.error.already_exists",
                "A role with ID '{}' already exists in realm with ID '{}'".
                format(role_id, realm_id))

        self.realms[realm_id].roles[role_id] = RouterRealmRole(
            role_id, role_config)

        realm = self.realms[realm_id].config['name']
        self._router_factory.add_role(realm, role_config)

        topic = u'{}.on_router_realm_role_started'.format(self._uri_prefix)
        event = self.realms[realm_id].roles[role_id].marshal()
        caller = details.caller if details else None
        self.publish(topic, event, options=PublishOptions(exclude=caller))

        self.log.info('role {role_id} on realm {realm_id} started',
                      realm_id=realm_id,
                      role_id=role_id,
                      role_config=role_config)
        return event
Пример #14
0
    def shutdown(self, restart=False, mode=None, details=None):
        """
        Explicitly stop this node.
        """
        if self._shutdown_requested:
            # we're already shutting down .. ignore ..
            return

        self._shutdown_requested = True
        self.log.info(
            'Node shutdown requested (restart={}, mode={}, reactor.running={}) ..'
            .format(restart, mode, self._reactor.running))

        term_print('CROSSBAR:NODE_SHUTDOWN_REQUESTED')

        try:
            # node shutdown information
            shutdown_info = {
                u'node_id': self._node._node_id,
                u'restart': restart,
                u'mode': mode,
                u'who': details.caller if details else None,
                u'when': utcnow(),
                u'was_clean': self._shutdown_was_clean,
            }

            if self._node._shutdown_complete:
                self._node._shutdown_complete.callback(shutdown_info)

            # publish management API event
            yield self.publish(u'{}.on_shutdown'.format(self._uri_prefix),
                               shutdown_info,
                               options=PublishOptions(
                                   exclude=details.caller if details else None,
                                   acknowledge=True))

            def stop_reactor():
                try:
                    self._reactor.stop()
                except ReactorNotRunning:
                    pass

            _SHUTDOWN_DELAY = 0.2
            self._reactor.callLater(_SHUTDOWN_DELAY, stop_reactor)

        except:
            self.log.failure()
            self._shutdown_requested = False
            raise

        else:
            returnValue(shutdown_info)
Пример #15
0
    def publish_ready(self):
        # signal that this worker is ready for setup. the actual setup procedure
        # will either be sequenced from the local node configuration file or remotely
        # from a management service
        yield self.publish('{}.on_worker_ready'.format(self._uri_prefix), {
            'type': self.WORKER_TYPE,
            'id': self.config.extra.worker,
            'pid': os.getpid(),
        },
                           options=PublishOptions(acknowledge=True))

        self.log.debug("Worker '{worker}' running as PID {pid}", worker=self.config.extra.worker, pid=os.getpid())
        term_print('CROSSBAR[{}]:WORKER_STARTED'.format(self.config.extra.worker))
Пример #16
0
 def publish_stopped(session, stop_details):
     self.log.info(
         "stopped component: {session} id={session_id}",
         session=class_name(session),
         session_id=session._session_id,
     )
     topic = self._uri_prefix + '.on_component_stop'
     event = {'id': id}
     caller = details.caller if details else None
     self.publish(topic, event, options=PublishOptions(exclude=caller))
     if not started_d.called:
         started_d.errback(Exception("Session left before being ready"))
     return event
Пример #17
0
        def success(proto):
            self.components[id] = ContainerComponent(id, config, proto, None)

            # publish event "on_component_start" to all but the caller
            #
            topic = 'crossbar.node.{}.worker.{}.container.on_component_start'.format(
                self.config.extra.node, self.config.extra.worker)
            event = {'id': id}
            self.publish(topic,
                         event,
                         options=PublishOptions(exclude=[details.caller]))

            return event
Пример #18
0
    def _stop_native_worker(self, worker_id, kill, details=None):

        if worker_id not in self._workers or not isinstance(
                self._workers[worker_id], NativeWorkerProcess):
            emsg = "Could not stop native worker: no native worker with ID '{}' currently running".format(
                worker_id)
            raise ApplicationError(u'crossbar.error.worker_not_running', emsg)

        worker = self._workers[worker_id]

        if worker.status != 'started':
            emsg = "Could not stop native worker: worker with ID '{}' is not in status 'started', but status: '{}')".format(
                worker_id, worker.status)
            raise ApplicationError(u'crossbar.error.worker_not_running', emsg)

        stop_info = {
            u'id': worker.id,
            u'type': worker.TYPE,
            u'kill': kill,
            u'who': details.caller if details else None,
            u'when': utcnow(),
        }

        # publish management API event
        #
        yield self.publish(u'{}.on_stop_requested'.format(self._uri_prefix),
                           stop_info,
                           options=PublishOptions(
                               exclude=details.caller if details else None,
                               acknowledge=True))

        # send SIGKILL or SIGTERM to worker
        #
        if kill:
            self.log.info("Killing {worker_type} worker with ID '{worker_id}'",
                          worker_type=worker.TYPE,
                          worker_id=worker_id)
            self._workers[worker_id].proto.transport.signalProcess("KILL")
        else:
            self.log.info(
                "Stopping {worker_type} worker with ID '{worker_id}'",
                worker_type=worker.TYPE,
                worker_id=worker_id)
            self._workers[worker_id].factory.stopFactory()
            self._workers[worker_id].proto.transport.signalProcess('TERM')

        # wait until the worker is actually done before we return from
        # this call
        yield self._workers[worker_id].proto.is_closed

        returnValue(stop_info)
Пример #19
0
    def _process(self, request, event):

        if 'topic' not in event:
            return self._deny_request(
                request, 400,
                "invalid request event - missing 'topic' in HTTP/POST body")

        topic = event.pop('topic')

        args = event.pop('args', [])
        kwargs = event.pop('kwargs', {})
        options = event.pop('options', {})

        publish_options = PublishOptions(acknowledge=True,
                                         exclude=options.get('exclude', None),
                                         eligible=options.get(
                                             'eligible', None))

        kwargs['options'] = publish_options

        # http://twistedmatrix.com/documents/current/web/howto/web-in-60/asynchronous-deferred.html

        d = self._session.publish(topic, *args, **kwargs)

        def on_publish_ok(pub):
            res = {'id': pub.id}
            self.log.debug("request succeeded with result {res}", res=res)
            body = json.dumps(res, separators=(',', ':'))
            if six.PY3:
                body = body.encode('utf8')

            request.setHeader('content-type',
                              'application/json; charset=UTF-8')
            request.setHeader(
                'cache-control',
                'no-store, no-cache, must-revalidate, max-age=0')
            request.setResponseCode(202)
            request.write(body)
            request.finish()

        def on_publish_error(err):
            emsg = "PublisherResource - request failed with error {0}\n".format(
                err.value)
            self.log.debug(emsg)
            request.setResponseCode(400)
            request.write(emsg)
            request.finish()

        d.addCallbacks(on_publish_ok, on_publish_error)

        return server.NOT_DONE_YET
Пример #20
0
    def set_process_stats_monitoring(self, interval, details=None):
        """
        Enable/disable periodic publication of process statistics.

        :param interval: The monitoring interval in seconds. Set to 0 to disable monitoring.
        :type interval: float
        """
        self.log.debug("{cls}.set_process_stats_monitoring(interval = {interval})",
                       cls=self.__class__.__name__, interval=interval)

        if self._pinfo:

            stats_monitor_set_topic = '{}.on_process_stats_monitoring_set'.format(self._uri_prefix)

            # stop and remove any existing monitor
            if self._pinfo_monitor:
                self._pinfo_monitor.stop()
                self._pinfo_monitor = None

                self.publish(stats_monitor_set_topic, 0, options=PublishOptions(exclude=details.caller))

            # possibly start a new monitor
            if interval > 0:
                stats_topic = '{}.on_process_stats'.format(self._uri_prefix)

                def publish_stats():
                    stats = self._pinfo.get_stats()
                    self._pinfo_monitor_seq += 1
                    stats[u'seq'] = self._pinfo_monitor_seq
                    self.publish(stats_topic, stats)

                self._pinfo_monitor = LoopingCall(publish_stats)
                self._pinfo_monitor.start(interval)

                self.publish(stats_monitor_set_topic, interval, options=PublishOptions(exclude=details.caller))
        else:
            emsg = "Cannot setup process statistics monitor: required packages not installed"
            raise ApplicationError(u"crossbar.error.feature_unavailable", emsg)
Пример #21
0
def _(session, details):
    print("joined: {}".format(session))
    topic_name = u"io.crossbar.demo.public.foo"

    while session.is_connected():
        print("publish to '{}'".format(topic_name))
        session.publish(
            topic_name,
            1,
            2,
            foo="bar",
            options=PublishOptions(exclude_me=False),
        )
        yield sleep(1)
Пример #22
0
 def _tick(self):
     self._tick_no += 1
     now = time.time()
     self._tick_sent[self._tick_no] = now
     try:
         pub = yield self.publish(u'{}.on_alive'.format(self._prefix),
                                  self._tick_no,
                                  options=PublishOptions(acknowledge=True,
                                                         exclude_me=False))
     except:
         self.log.failure()
     else:
         self.log.info('TICK sent [tick {}, pub {}]'.format(
             self._tick_no, pub.id))
Пример #23
0
 def on_event(*args, **kwargs):
     details = kwargs.pop('details')
     topic = u"cdc." + details.topic
     try:
         yield self._management_session.publish(
             topic,
             *args,
             options=PublishOptions(acknowledge=True),
             **kwargs)
     except Exception as e:
         self.log.error(e)
     else:
         self.log.debug("Forwarded event on topic '{topic}'",
                        topic=topic)
Пример #24
0
    def publish_ready(self):
        # signal that this worker is ready for setup. the actual setup procedure
        # will either be sequenced from the local node configuration file or remotely
        # from a management service
        #
        yield self.publish('crossbar.node.{}.on_worker_ready'.format(
            self.config.extra.node), {
                'type': self.WORKER_TYPE,
                'id': self.config.extra.worker,
                'pid': os.getpid()
            },
                           options=PublishOptions(acknowledge=True))

        self.log.info("Worker ready to roll!")
Пример #25
0
    def onJoin(self, details):

        def on_event(i):
            print("Got event: {}".format(i))

        yield from self.subscribe(on_event, 'com.myapp.topic1')

        counter = 0
        while True:
            publication = yield from self.publish('com.myapp.topic1', counter,
                                                  options=PublishOptions(acknowledge=True, discloseMe=True, excludeMe=False))
            print("Event published with publication ID {}".format(publication.id))
            counter += 1
            yield from asyncio.sleep(1)
Пример #26
0
        def run(txn):
            ## FIXME: make the following into 1 (atomic) SQL statement
            ## => does SQLite feature "UPDATE .. RETURNING"?
            txn.execute("UPDATE votes SET count = count + 1 WHERE item = ?",
                        [item])
            txn.execute("SELECT count FROM votes WHERE item = ?", [item])
            count = int(txn.fetchone()[0])

            self.publish("com.votegame.onvote",
                         item,
                         count,
                         options=PublishOptions(excludeMe=False))

            return count
Пример #27
0
    def onJoin(self, details):
        print("session attached")
        print("  authid: {}".format(details.authid))
        print("authrole: {}".format(details.authrole))

        def got_heartbeat(name, counter):
            print("hearbeat: {}: {}".format(name, counter))

        for name in ['alice', 'bob', 'carol', 'dave', 'erin']:
            yield self.subscribe(
                partial(got_heartbeat, name),
                'public.heartbeat.{}'.format(name),
            )

        counter = 0
        topic = 'public.heartbeat.alice'
        while True:
            print("publish '{}'".format(topic))
            self.publish(
                topic,
                counter,
                options=PublishOptions(
                    exclude_authid=['bob'],
                    exclude=12345,
                ),
            )
            if counter % 2:
                self.publish(
                    topic,
                    "to everyone with 'alpha' role",
                    options=PublishOptions(
                        eligible_authrole=['alpha'],
                        exclude_me=False,
                    ),
                )
            counter += 1
            yield sleep(3)
Пример #28
0
    def test2(self):
        """
        The following produces this trace:

        https://gist.githubusercontent.com/oberstet/510b1d5d1fe6a65f78d439dc6b678c33/raw/2a9c6959db987716d3ccbc20c5bec5ccb146aee9/gistfile1.txt
        """

        # unacked publish to topic with no subscribers
        #
        topic = u'com.example.r{}'.format(random.randint(0, 10000))
        self.publish(topic, u'hey')

        # acked publish to topic with no subscribers
        #
        topic = u'com.example.r{}'.format(random.randint(0, 10000))
        yield self.publish(topic,
                           u'hey',
                           options=PublishOptions(acknowledge=True))

        # unacked publish to topic with 1 subscriber (ourself)
        #
        topic = u'com.example.r{}'.format(random.randint(0, 10000))
        sub = yield self.subscribe(lambda msg: print(msg), topic)
        self.publish(topic, u'hey', options=PublishOptions(exclude_me=False))

        # acked publish to topic with 1 subscriber (ourself)
        #
        topic = u'com.example.r{}'.format(random.randint(0, 10000))
        sub = yield self.subscribe(lambda msg: print(msg), topic)
        yield self.publish(topic,
                           u'hey',
                           options=PublishOptions(acknowledge=True,
                                                  exclude_me=False))

        # resubscribe to a topic we are already subscribed to
        #
        sub = yield self.subscribe(lambda msg: print(msg), topic)
Пример #29
0
    def _stop_native_worker(self, wtype, id, kill, details=None):

        assert (wtype in ['router', 'container', 'websocket-testee'])

        if id not in self._workers or self._workers[id].TYPE != wtype:
            emsg = "Could not stop native worker: no {} worker with ID '{}' currently running".format(
                wtype, id)
            raise ApplicationError(u'crossbar.error.worker_not_running', emsg)

        worker = self._workers[id]

        if worker.status != 'started':
            emsg = "Could not stop native worker: worker with ID '{}' is not in status 'started', but status: '{}')".format(
                id, worker.status)
            raise ApplicationError(u'crossbar.error.worker_not_running', emsg)

        stop_info = {
            'id': worker.id,
            'type': wtype,
            'kill': kill,
            'who': details.caller if details else None,
            'when': utcnow()
        }

        # publish management API event
        #
        yield self.publish(
            'crossbar.node.{}.worker.{}.on_stop_requested'.format(
                self._node_id, worker.id),
            stop_info,
            options=PublishOptions(
                exclude=[details.caller] if details else None,
                acknowledge=True))

        # send SIGKILL or SIGTERM to worker
        #
        if kill:
            self.log.info("Killing {wtype} worker with ID '{id}'",
                          wtype=wtype,
                          id=id)
            self._workers[id].proto.transport.signalProcess("KILL")
        else:
            self.log.info("Stopping {wtype} worker with ID '{id}'",
                          wtype=wtype,
                          id=id)
            self._workers[id].factory.stopFactory()
            self._workers[id].proto.transport.signalProcess('TERM')

        returnValue(stop_info)
Пример #30
0
    async def onJoin(self, details):
        print('Seller session joined', details)
        try:
            delegate_key = self._ethkey_raw
            delegate_adr = self._ethkey.public_key.to_canonical_address()
            print('Using delegate adr:', delegate_adr)

            config = await self.call('xbr.marketmaker.get_config')
            print('Using market maker adr:', config['marketmaker'])

            market_maker_adr = binascii.a2b_hex(config['marketmaker'][2:])

            api_id = uuid.UUID('627f1b5c-58c2-43b1-8422-a34f7d3f5a04').bytes
            topic = 'io.crossbar.example'
            counter = 1

            # 5 XBR / 10s
            price = 5 * 10**18
            interval = 10

            seller = SimpleSeller(market_maker_adr, delegate_key)
            seller.add(api_id, topic, price, interval, None)

            balance = await seller.start(self)
            balance = int(balance / 10**18)
            print("Remaining balance: {} XBR".format(balance))

            self.log.info(
                'Seller session ready! Starting to publish events ..')
            running = True
            while running:
                payload = {'data': 'py-seller', 'counter': counter}
                key_id, enc_ser, ciphertext = await seller.wrap(
                    api_id, topic, payload)

                pub = await self.publish(
                    topic,
                    key_id,
                    enc_ser,
                    ciphertext,
                    options=PublishOptions(acknowledge=True))

                print('Published event {}: {}'.format(pub.id, payload))

                counter += 1
                await sleep(1)
        except:
            self.log.failure()
            self.leave()