nicholasf / spoonbot

Spoonbot - an IRC bot written in Elixir with a simple command syntax.
16 stars 6 forks source link

Commands and Elixir Protocols and Network Protocols #4

Open nicholasf opened 10 years ago

nicholasf commented 10 years ago

This is an explanation of how to write commands for spoonbot that map generic functionality to network specific protocols using Elixir protocols.

The function exists - e.g. an SQL select statement

The network protocols are quite different - 
* HTTP behaviour is invoked via a URL
* IRC is a listener to a stream

(invocation) - HTTP needs to decide how to publish the resource based upon what it does - it needs to specify a verb *and* a name. The function has no way of describing that.

(listening) - IRC needs to just specify a name.

So, whatever loads the command into the HTTP bridge would need to make a judgement about the verb. Can a protocol implementation do that?

Yes, if the Command is specific to the function.

defprotocol HttpBridgeCommand do
    def url
end

defimpl HttpBridgeCommand, for: SqlSelector do
    def url do
        { :get, '/sqlselector/:table' } 
        #where table will behave as a parameter in the http request
    end    
end

defimpl IrcBridgeCommand, for: SqlSelector do
    def listen do
        #matching logic for 'PRIVMSG spoonbot: show me everything in <table>'
    end
end

defmodule SqlSelector do
    #assume the sql connection is gained beforehand 
    def invoke(connection, table) do
        connection.execute("SELECT * FROM #{table}")
    end
end

defmodule HttpBridge do
    #initialises by loading an array of commands, e.g. SqlSelector
    #this means it can gain a URL from the command
    #for e.g. (in psuedocode)

    http.get command.url, command.invoke

    #then it simply calls invoke
end
nicholasf commented 10 years ago

The above would work. I don't think it's a particularly good use of Elixir protocols to achieve the desired effect though.

Ideally the correct metadata (module attributes) could be put upon the function in the command itself, so the defimpl could decide how to build the URL ...