Permalink
Browse files

Merge pull request #945 from meejah/newapi-functional-component

A way to configure a 'functional' component
  • Loading branch information...
2 parents 80372be + 75a98bc commit b713aaae45b8267dc86ed83385edb14b0a03a6a0 @oberstet oberstet committed on GitHub Dec 29, 2016
Showing with 49 additions and 1 deletion.
  1. +19 −1 crossbar/common/checkconfig.py
  2. +30 −0 crossbar/worker/__init__.py
@@ -2020,7 +2020,7 @@ def check_router_component(component):
raise InvalidConfigException("missing mandatory attribute 'type' in component")
ctype = component['type']
- if ctype not in ['wamplet', 'class']:
+ if ctype not in ['wamplet', 'class', 'function']:
raise InvalidConfigException("invalid value '{}' for component type".format(ctype))
if ctype == 'wamplet':
@@ -2048,6 +2048,24 @@ def check_router_component(component):
'extra': (False, None),
}, component, "invalid component configuration")
+ elif ctype == 'function':
+ check_dict_args({
+ 'id': (False, [six.text_type]),
+ 'type': (True, [six.text_type]),
+ 'realm': (True, [six.text_type]),
+ 'role': (False, [six.text_type]),
+
+ 'callbacks': (False, [dict]),
+ }, component, "invalid component configuration")
+ if 'callbacks' in component:
+ valid_callbacks = ['join', 'leave', 'connect', 'disconnect']
+ for name in component['callbacks'].keys():
+ if name not in valid_callbacks:
+ raise InvalidConfigException(
+ "Invalid callback name '{}' (valid are: {})".format(
+ name, valid_callbacks
+ )
+ )
else:
raise InvalidConfigException('logic error')
@@ -92,6 +92,36 @@ def _appsession_loader(config):
log.error(emsg)
raise ApplicationError(u"crossbar.error.class_import_failed", emsg)
+ elif config['type'] == 'function':
+ callbacks = {}
+ for name, funcref in config.get('callbacks', {}).items():
+ if '.' not in funcref:
+ raise ApplicationError(
+ u"crossbar.error",
+ "no '.' in callback reference '{}'".format(funcref),
+ )
+
+ try:
+ package, func = funcref.rsplit('.', 1)
+
+ module = importlib.import_module(package)
+ callbacks[name] = getattr(module, func)
+
+ except Exception:
+ emsg = "Failed to import package '{}' (for '{}')\n{}".format(
+ package, funcref, Failure().getTraceback())
+ log.error('{msg}', msg=emsg)
+ raise ApplicationError(u"crossbar.error.class_import_failed", emsg)
+
+ # while the "component" callback is usually an
+ # ApplicationSession class, it can be anything that takes a
+ # "config" arg (must return an ApplicationSession instance)
+ def component(config):
+ session = ApplicationSession(config)
+ for name, fn in callbacks.items():
+ session.on(name, fn)
+ return session
+
else:
raise ApplicationError(
u"crossbar.error.invalid_configuration",

0 comments on commit b713aaa

Please sign in to comment.