Class: Messed

Inherits:
Object
  • Object
show all
Includes:
Controller::Helper, Controller::Processing, Controller::Respond, Logger::LoggingModule
Defined in:
lib/messed.rb,
lib/messed/queue.rb,
lib/messed/tasks.rb,
lib/messed/booter.rb,
lib/messed/logger.rb,
lib/messed/matcher.rb,
lib/messed/message.rb,
lib/messed/session.rb,
lib/messed/em_runner.rb,
lib/messed/interface.rb,
lib/messed/controller.rb,
lib/messed/tasks/runner.rb,
lib/messed/tasks/status.rb,
lib/messed/configuration.rb,
lib/messed/tasks/console.rb,
lib/messed/message/twitter.rb,
lib/messed/queue/beanstalk.rb,
lib/messed/interface/runner.rb,
lib/messed/session/memcache.rb,
lib/messed/tasks/generation.rb,
lib/messed/controller/helper.rb,
lib/messed/interface/adapter.rb,
lib/messed/controller/respond.rb,
lib/messed/util/remote_status.rb,
lib/messed/controller/processing.rb,
lib/messed/interface/adapter/twitter_search.rb,
lib/messed/interface/adapter/twitter_sender.rb,
lib/messed/interface/adapter/twitter_consumer.rb,
lib/messed/interface/adapter/twitter_streaming.rb

Defined Under Namespace

Modules: Tasks, Util Classes: Booter, Configuration, Controller, EMRunner, Interface, Logger, Matcher, Message, Queue, Session

Instance Attribute Summary collapse

Attributes included from Controller::Helper

#message, #params, #session

Instance Method Summary collapse

Methods included from Controller::Respond

#clear_responses, included, #reply, #responses, #say, #set_response, #whisper

Methods included from Controller::Processing

included

Methods included from Logger::LoggingModule

included, #logger, #logger=

Constructor Details

#initialize(type = :twitter, &block) ⇒ Messed

Returns a new instance of Messed.



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/messed.rb', line 42

def initialize(type = :twitter, &block)
  @type = type
  @matchers = []
  @session_store = Session::Memcache.new
  @messages_sent_count = 0
  @messages_received_count = 0
  
  @interface = self
  @name = 'Application'
  match(&block) if block
end

Instance Attribute Details

#booterObject

Returns the value of attribute booter.



38
39
40
# File 'lib/messed.rb', line 38

def booter
  @booter
end

#controllerObject

Returns the value of attribute controller.



38
39
40
# File 'lib/messed.rb', line 38

def controller
  @controller
end

#current_matcherObject

Returns the value of attribute current_matcher.



38
39
40
# File 'lib/messed.rb', line 38

def current_matcher
  @current_matcher
end

#incomingObject

Returns the value of attribute incoming.



39
40
41
# File 'lib/messed.rb', line 39

def incoming
  @incoming
end

#interfaceObject (readonly)

Returns the value of attribute interface.



39
40
41
# File 'lib/messed.rb', line 39

def interface
  @interface
end

#last_message_receivedObject (readonly)

Returns the value of attribute last_message_received.



39
40
41
# File 'lib/messed.rb', line 39

def last_message_received
  @last_message_received
end

#last_message_sentObject (readonly)

Returns the value of attribute last_message_sent.



39
40
41
# File 'lib/messed.rb', line 39

def last_message_sent
  @last_message_sent
end

#matchersObject (readonly)

Returns the value of attribute matchers.



39
40
41
# File 'lib/messed.rb', line 39

def matchers
  @matchers
end

#messages_received_countObject (readonly)

Returns the value of attribute messages_received_count.



39
40
41
# File 'lib/messed.rb', line 39

def messages_received_count
  @messages_received_count
end

#messages_sent_countObject (readonly)

Returns the value of attribute messages_sent_count.



39
40
41
# File 'lib/messed.rb', line 39

def messages_sent_count
  @messages_sent_count
end

#nameObject (readonly)

Returns the value of attribute name.



39
40
41
# File 'lib/messed.rb', line 39

def name
  @name
end

#outgoingObject

Returns the value of attribute outgoing.



39
40
41
# File 'lib/messed.rb', line 39

def outgoing
  @outgoing
end

#session_storeObject (readonly)

Returns the value of attribute session_store.



39
40
41
# File 'lib/messed.rb', line 39

def session_store
  @session_store
end

#typeObject (readonly)

Returns the value of attribute type.



39
40
41
# File 'lib/messed.rb', line 39

def type
  @type
end

Instance Method Details

#increment_messages_received!Object



229
230
231
232
# File 'lib/messed.rb', line 229

def increment_messages_received!
  @messages_received_count += 1
  @last_message_received = Time.new
end

#increment_messages_sent!Object



224
225
226
227
# File 'lib/messed.rb', line 224

def increment_messages_sent!
  @messages_sent_count += 1
  @last_message_sent = Time.new
end

#match(&block) ⇒ Object



54
55
56
# File 'lib/messed.rb', line 54

def match(&block)
  instance_eval(&block)
end

#message_classObject



62
63
64
# File 'lib/messed.rb', line 62

def message_class
  Message.class_for_type(type)
end

#otherwise(options = nil, &block) ⇒ Object Also known as: always



85
86
87
88
# File 'lib/messed.rb', line 85

def otherwise(options = nil, &block)
  matchers << Matcher::Always.new(&block)
  matchers.last.destination = block
end

#process(message) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/messed.rb', line 146

def process(message)
  logger.debug("Processing `#{message.body}'")
  increment_messages_received!
  responses = []
  
  self.message = message
  
  session_store.with(message.unique_id) do |session|
    self.session = session
    
    matchers.find do |matcher|
      if matcher.match?(message)
        self.current_matcher = matcher
        controller = process_destination(matcher.destination)
        responses.concat(controller.responses)
        matcher.stop_processing?
      else
        false
      end
    end
  
    controller.reset_processing! if controller.respond_to?(:reset_processing!)
    reset_processing!
  end
  responses
end

#process_incoming(continue_forever) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/messed.rb', line 126

def process_incoming(continue_forever)
  @connection.reserve(continue_forever ? nil : 0.5) { |job|
    begin
      message = message_class.from_json(job.body)
      process_responses process(message)
      job.delete do
        process_incoming(continue_forever)
      end
    rescue JSON::ParserError
      # unrecoverable
      logger.error "message #{job.body.inspect} not in JSON format"
      job.delete do
        process_incoming(continue_forever)
      end
    end
  }.on_error { |message|
    EM.stop_event_loop
  }
end

#process_responses(responses) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
# File 'lib/messed.rb', line 203

def process_responses(responses)
  if responses && !responses.empty?
    logger.debug("Putting response #{responses.first.body} onto outgoing queue")
    @connection.put(responses.shift.to_json) do
      increment_messages_sent!
      process_responses(responses)
    end
  else
    logger.debug("No response.")
  end
end

#start(continue_forever = true) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/messed.rb', line 99

def start(continue_forever = true)
  if EM.reactor_running?
    if booter
      EM.start_server(status_host, status_port, EMRunner::StatusHandler) do |c|
        c.interface = self
      end
      logger.info "Status handler for #{self.class} started on #{status_host}:#{status_port}"
      booter.write_pid_file(booter.configuration.application.pid_file)
    end
    
    @connection = EM::Beanstalk.new
    @connection.watch(incoming.tube) do
      @connection.use(outgoing.tube) do
        process_incoming(continue_forever)
      end
    end
  else
    EM.run {
      start(continue_forever)
    }
  end
end

#statusObject



215
216
217
218
219
220
221
222
# File 'lib/messed.rb', line 215

def status
  {
    :messages_received_count => messages_received_count,
    :messages_sent_count => messages_sent_count,
    :last_message_received => last_message_received,
    :last_message_sent => last_message_sent
  }
end

#status_hostObject



95
96
97
# File 'lib/messed.rb', line 95

def status_host
  booter.configuration.application.status_address || '0.0.0.0'
end

#status_portObject



91
92
93
# File 'lib/messed.rb', line 91

def status_port
  booter.configuration.application.status_port || 19191
end

#stopObject



122
123
124
# File 'lib/messed.rb', line 122

def stop
  Process.kill("INT", booter.read_pid_file(booter.configuration.application.pid_file))
end

#with(*args, &block) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/messed.rb', line 76

def with(*args, &block)
  matchers << if args.first.is_a?(Hash)
    Matcher::Conditional.new(nil, args.first)
  else
    Matcher::Conditional.new(*args, &block)
  end
  matchers.last.destination = block
end