fixbot/api/amp.py
author Tero Marttila <terom@fixme.fi>
Sat, 20 Feb 2010 23:06:43 +0200
changeset 64 8574aeff9b36
parent 62 e4db89a5f6bc
permissions -rw-r--r--
blind error handling tweaks
from twisted.protocols import amp
from twisted.python import log

from fixbot.module import ModuleInfo, Event

class CmdModuleRegister (amp.Command) :
    """
        Register module
    """

    arguments = [
        ('name',    amp.String()),
    ]

class CmdModuleEvent (amp.Command) :
    """
        Broadcast event
    """

    arguments = [
        ('type',    amp.String()),
        ('msg',     amp.String()),
    ]

class CmdModuleAbort (amp.Command) :
    """
        Module has failed and will now disconnect
    """

    arguments = [
        ('msg',     amp.String())   # string describing the error occuring
    ]

    requiresAnswer = False

class ServerProtocol (amp.AMP) :
    """
        Nexus-side command handler
    """

    # the registered ModuleInfo
    module = None
    
    def connectionMade (self) :
        log.msg("Module connecting from: %s" % (self.transport.getPeer()))


    def connectionLost (self, reason) :
        log.err(reason, "Module lost")
        
        if self.module :
            # drop it
            self.factory.nexus.unregisterModule(self.module, reason.getErrorMessage())


    @CmdModuleRegister.responder
    def on_ModuleRegister (self, name) :
        # construct the ModuleInfo
        mi = ModuleInfo()
        mi.name = name

        log.msg("Module registered: %s" % (mi))
        
        # register
        self.factory.nexus.registerModule(mi, self)
        self.module = mi

        # ok
        return {}

    @CmdModuleEvent.responder
    def on_ModuleEvent (self, type, msg) :
        # as Event
        e = Event(self.module, type, msg)
        
        # publish
        self.factory.nexus.handleEvent(e)

        # ok
        return {}
    
    @CmdModuleAbort.responder
    def on_ModuleAbort (self, msg) :
        # unhook
        module = self.module
        self.module = None

        # report
        self.factory.nexus.unregisterModule(self.module, msg)
        
        # XXX: stop accepting commands etc?

class ClientProtocol (amp.AMP) :
    """
        Module-side command sender/handler
    """
    

    def connectionMade (self) :
        """
            Connected to nexus, send ModuleRegister
        """
        
        # register
        self.sendModuleRegister(self.factory.name).addCallback(self._ModuleRegisterOK)
    
    def connectionLost (self, reason) :
        """
            Disconnected from nexus, for whatever reason...
        """
        
        log.err(reason, "API connection lost")

        # XXX: was this expected? Reconnect?

    def sendModuleRegister (self, name) :
        """
            Register with given module name
        """

        return self.callRemote(CmdModuleRegister, name=name)


    def _ModuleRegisterOK (self, ret) :
        """
            Registered with nexus, commence operation
        """

        self.factory._onRegistered(self)


    def sendEvent (self, event) :
        """
            Broadcast event to nexus
        """
        
        self.callRemote(CmdModuleEvent, type=event.type, msg=event.msg)

    def sendModuleAbort (self, msg) :
        """
            Send CmdModuleAbort - no response is expected
        """

        self.callRemote(CmdModuleAbort, msg=msg)


    def abort (self, msg) :
        """
            Send abort message and drop connection
        """

        # disconnect. This should leave the transport to flush buffers, and then call connectionLost
        # should also stop us from sending any more commands
        self.transport.loseConnection()