mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 04:27:16 +02:00
Added remote function call abilities to AMP protocol, courtesy of patch by user Shell.
This allows for Server to call functions on Portal and vice-versa. Some rewrites and cleanup done before applying /Griatch.
This commit is contained in:
parent
049cc84be7
commit
592bc26b99
2 changed files with 71 additions and 5 deletions
|
|
@ -22,7 +22,8 @@ except ImportError:
|
|||
import pickle
|
||||
from twisted.protocols import amp
|
||||
from twisted.internet import protocol
|
||||
from src.utils.utils import to_str
|
||||
from twisted.internet.defer import Deferred
|
||||
from src.utils.utils import to_str, variable_from_module
|
||||
|
||||
# these are only needed on the server side, so we delay loading of them
|
||||
# so as to not have to load them on the portal too. Note: It's doubtful
|
||||
|
|
@ -133,6 +134,8 @@ class AmpClientFactory(protocol.ReconnectingClientFactory):
|
|||
protocol.ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
|
||||
|
||||
|
||||
# AMP Communication Command types
|
||||
|
||||
class MsgPortal2Server(amp.Command):
|
||||
"""
|
||||
Message portal -> server
|
||||
|
|
@ -198,6 +201,23 @@ class PortalAdmin(amp.Command):
|
|||
errors = [(Exception, 'EXCEPTION')]
|
||||
response = []
|
||||
|
||||
class FunctionCall(amp.Command):
|
||||
"""
|
||||
Bidirectional
|
||||
|
||||
Sent when either process needs to call an
|
||||
arbitrary function in the other.
|
||||
"""
|
||||
arguments = [('module', amp.String()),
|
||||
('function', amp.String()),
|
||||
('args', amp.String()),
|
||||
('kwargs', amp.String())]
|
||||
errors = [(Exception, 'EXCEPTION')]
|
||||
response = [('result', amp.String())]
|
||||
|
||||
|
||||
# Helper functions
|
||||
|
||||
dumps = lambda data: to_str(pickle.dumps(data, pickle.HIGHEST_PROTOCOL))
|
||||
loads = lambda data: pickle.loads(to_str(data))
|
||||
|
||||
|
|
@ -469,3 +489,43 @@ class AMPProtocol(amp.AMP):
|
|||
sessid=sessid,
|
||||
operation=operation,
|
||||
data=data).addErrback(self.errback, "PortalAdmin")
|
||||
|
||||
# Extra functions
|
||||
|
||||
def amp_function_call(self, module, function, args, kwargs):
|
||||
"""
|
||||
This allows Portal- and Server-process to call an arbitrary function
|
||||
in the other process. It is intended for use by plugin modules.
|
||||
"""
|
||||
args = loads(args)
|
||||
kwargs = loads(kwargs)
|
||||
|
||||
# call the function (don't catch tracebacks here)
|
||||
result = variable_from_module(module, function)(*args, **kwargs)
|
||||
|
||||
if isinstance(result, Deferred):
|
||||
# if result is a deferred, attach handler to properly wrap the return value
|
||||
result.addCallback(lambda r: {"result":dumps(r)})
|
||||
return result
|
||||
else:
|
||||
return {'result':dumps(result)}
|
||||
FunctionCall.responder(amp_function_call)
|
||||
|
||||
|
||||
def call_remote_FunctionCall(self, modulepath, functionname, *args, **kwargs):
|
||||
"""
|
||||
Access method called by either process. This will call an arbitrary function
|
||||
on the other process (On Portal if calling from Server and vice versa).
|
||||
|
||||
Inputs:
|
||||
modulepath (str) - python path to module holding function to call
|
||||
functionname (str) - name of function in given module
|
||||
*args, **kwargs will be used as arguments/keyword args for the remote function call
|
||||
Returns:
|
||||
A deferred that fires with the return value of the remote function call
|
||||
"""
|
||||
return self.callRemote(FunctionCall,
|
||||
module=modulepath,
|
||||
function=functionname,
|
||||
args=dumps(args),
|
||||
kwargs=dumps(kwargs)).addCallback(lambda r: loads(r["result"])).addErrback(self.errback, "FunctionCall")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue