messed 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -0
- data/README.rdoc +22 -0
- data/Rakefile +76 -0
- data/VERSION +1 -0
- data/application_spec/Rakefile +12 -0
- data/application_spec/app/runner.rb +3 -0
- data/application_spec/bin/runner +18 -0
- data/application_spec/bin/status +36 -0
- data/application_spec/bin/web +29 -0
- data/application_spec/config/environment.rb +8 -0
- data/application_spec/config/environments/development.rb +0 -0
- data/application_spec/log/development.log +6 -0
- data/application_spec/spec/application_spec.rb +12 -0
- data/application_spec/spec/spec.opts +7 -0
- data/application_spec/spec/spec_helper.rb +42 -0
- data/bin/messed +9 -0
- data/lib/messed/booter.rb +114 -0
- data/lib/messed/configuration.rb +94 -0
- data/lib/messed/controller/helper.rb +8 -0
- data/lib/messed/controller/processing.rb +22 -0
- data/lib/messed/controller/respond.rb +48 -0
- data/lib/messed/controller.rb +17 -0
- data/lib/messed/em_runner.rb +50 -0
- data/lib/messed/interface/adapter/sms.rb +4 -0
- data/lib/messed/interface/adapter/twitter_consumer.rb +35 -0
- data/lib/messed/interface/adapter/twitter_search.rb +111 -0
- data/lib/messed/interface/adapter/twitter_sender.rb +44 -0
- data/lib/messed/interface/adapter/twitter_streaming.rb +50 -0
- data/lib/messed/interface/adapter.rb +68 -0
- data/lib/messed/interface/runner.rb +20 -0
- data/lib/messed/interface.rb +74 -0
- data/lib/messed/logger.rb +50 -0
- data/lib/messed/matcher.rb +50 -0
- data/lib/messed/message/twitter.rb +23 -0
- data/lib/messed/message.rb +35 -0
- data/lib/messed/queue/beanstalk.rb +56 -0
- data/lib/messed/queue.rb +17 -0
- data/lib/messed/session/memcache.rb +40 -0
- data/lib/messed/session.rb +7 -0
- data/lib/messed/tasks/console.rb +70 -0
- data/lib/messed/tasks/generation.rb +12 -0
- data/lib/messed/tasks/runner.rb +50 -0
- data/lib/messed/tasks/status.rb +37 -0
- data/lib/messed/tasks.rb +9 -0
- data/lib/messed/util/remote_status.rb +45 -0
- data/lib/messed.rb +235 -0
- data/patterns/messed/Pattern +24 -0
- data/patterns/messed/Rakefile +12 -0
- data/patterns/messed/app/runner.rb +5 -0
- data/patterns/messed/bin/console +3 -0
- data/patterns/messed/bin/runner +3 -0
- data/patterns/messed/bin/status +3 -0
- data/patterns/messed/bin/web +13 -0
- data/patterns/messed/config/environment.rb +15 -0
- data/patterns/messed/config/environments/development.rb +2 -0
- data/patterns/messed/config/environments/production.rb +0 -0
- data/patterns/messed/config/environments/test.rb +0 -0
- data/patterns/messed/spec/application_spec.rb +12 -0
- data/patterns/messed/spec/spec.opts +7 -0
- data/patterns/messed/spec/spec_helper.rb +44 -0
- data/spec/adapter/applications/twitter_search/app/application.rb +3 -0
- data/spec/adapter/applications/twitter_search/app/runner.rb +7 -0
- data/spec/adapter/applications/twitter_search/bin/incoming +89 -0
- data/spec/adapter/applications/twitter_search/bin/runner +21 -0
- data/spec/adapter/applications/twitter_search/bin/status +36 -0
- data/spec/adapter/applications/twitter_search/config/environment.rb +11 -0
- data/spec/adapter/applications/twitter_search/config/environments/development.rb +0 -0
- data/spec/adapter/applications/twitter_search/log/development.log +1006 -0
- data/spec/adapter/applications/twitter_sender/app/application.rb +0 -0
- data/spec/adapter/applications/twitter_sender/app/runner.rb +0 -0
- data/spec/adapter/applications/twitter_sender/bin/incoming +89 -0
- data/spec/adapter/applications/twitter_sender/bin/runner +21 -0
- data/spec/adapter/applications/twitter_sender/bin/status +36 -0
- data/spec/adapter/applications/twitter_sender/config/environment.rb +11 -0
- data/spec/adapter/applications/twitter_sender/config/environments/development.rb +0 -0
- data/spec/adapter/applications/twitter_sender/log/development.log +146 -0
- data/spec/adapter/http/direct_message +0 -0
- data/spec/adapter/http/twitter_search +20 -0
- data/spec/adapter/http/update +0 -0
- data/spec/adapter/twitter_search_spec.rb +36 -0
- data/spec/adapter/twitter_sender_spec.rb +64 -0
- data/spec/booter_spec.rb +7 -0
- data/spec/fixtures/booter/app/application.rb +3 -0
- data/spec/fixtures/booter/app/runner.rb +7 -0
- data/spec/fixtures/booter/bin/incoming +89 -0
- data/spec/fixtures/booter/bin/runner +21 -0
- data/spec/fixtures/booter/bin/status +36 -0
- data/spec/fixtures/booter/config/environment.rb +15 -0
- data/spec/fixtures/booter/config/environments/development.rb +0 -0
- data/spec/fixtures/booter/log/development.log +11 -0
- data/spec/message_spec.rb +52 -0
- data/spec/session_spec.rb +34 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +8 -0
- data/test/app/runner.rb +5 -0
- data/test/config/environment.rb +15 -0
- data/test/config/environments/development.rb +2 -0
- data/test/config/environments/production.rb +0 -0
- data/test/config/environments/test.rb +0 -0
- data/test/spec/application_spec.rb +12 -0
- data/test/spec/spec_helper.rb +44 -0
- metadata +291 -0
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= Messed
|
2
|
+
|
3
|
+
== Short messaging framework
|
4
|
+
|
5
|
+
We deal with short messages all the time. Email, SMS, twitter and XMPP are examples of such. This framework attempts to make it simple to deal with these various types of services.
|
6
|
+
|
7
|
+
== Getting started
|
8
|
+
|
9
|
+
Generate your app, fill it in.
|
10
|
+
|
11
|
+
== Topology
|
12
|
+
|
13
|
+
/----------\ Worker /----------\
|
14
|
+
| | /-------\ Worker /-------\ | |
|
15
|
+
| Incoming |==> | Queue | ==> Worker ==> | Queue | ==> | Outgoing |
|
16
|
+
| | \-------/ Worker \-------/ | |
|
17
|
+
\----------/ Worker \----------/
|
18
|
+
|
19
|
+
== Sample app
|
20
|
+
|
21
|
+
Let's listen to every tweet your friend sends you, and, if its in delicious, add it, otherwise, reply with a message saying how much you enjoyed that link.
|
22
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
libdir = File.expand_path("lib")
|
2
|
+
$:.unshift(libdir) unless $:.include?(libdir)
|
3
|
+
|
4
|
+
require 'messed'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |s|
|
9
|
+
s.name = "messed"
|
10
|
+
s.description = s.summary = "A framework for short message paradigms"
|
11
|
+
s.email = "joshbuddy@gmail.com"
|
12
|
+
s.homepage = "http://github.com/joshbuddy/messed"
|
13
|
+
s.authors = ["Joshua Hull"]
|
14
|
+
s.files = FileList["[A-Z]*", "{lib,spec,bin,application_spec,patterns}/**/*"]
|
15
|
+
s.add_dependency 'eventmachine'
|
16
|
+
s.add_dependency 'em-http-request', '>=0.2.6'
|
17
|
+
s.add_dependency 'em-beanstalk', '>=0.0.6'
|
18
|
+
s.add_dependency 'hashify', '>=0.0.2'
|
19
|
+
s.add_dependency 'hwia', '>=1.0.2'
|
20
|
+
s.add_dependency 'twitter-stream', '>=0.1.3'
|
21
|
+
s.add_dependency 'activesupport'
|
22
|
+
s.add_dependency 'dressmaker', '>=0.0.3'
|
23
|
+
s.add_dependency 'beanstalk-client'
|
24
|
+
s.add_dependency 'rspec'
|
25
|
+
s.add_dependency 'json'
|
26
|
+
s.add_dependency 'thor'
|
27
|
+
end
|
28
|
+
Jeweler::GemcutterTasks.new
|
29
|
+
rescue LoadError
|
30
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
31
|
+
end
|
32
|
+
|
33
|
+
require 'spec'
|
34
|
+
require 'spec/rake/spectask'
|
35
|
+
task :spec => ['spec:all', 'spec:application']
|
36
|
+
namespace(:spec) do
|
37
|
+
Spec::Rake::SpecTask.new(:all) do |t|
|
38
|
+
t.spec_opts ||= []
|
39
|
+
t.spec_opts << "-rubygems"
|
40
|
+
t.spec_opts << "--options" << "spec/spec.opts"
|
41
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
42
|
+
end
|
43
|
+
|
44
|
+
Spec::Rake::SpecTask.new(:application) do |t|
|
45
|
+
ENV['MESSED_HOME'] = '..'
|
46
|
+
t.ruby_opts ||= []
|
47
|
+
t.ruby_opts << '-Capplication_spec'
|
48
|
+
t.spec_opts ||= []
|
49
|
+
t.spec_opts << "-rubygems"
|
50
|
+
t.spec_opts << "--options" << "spec/spec.opts"
|
51
|
+
t.spec_files = FileList['application_spec/spec/**/*_spec.rb'].map{|f| f[/application_spec\/(.*)/, 1]}
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "Run all examples with RCov"
|
57
|
+
Spec::Rake::SpecTask.new('spec_with_rcov') do |t|
|
58
|
+
t.spec_files = FileList['spec/**/*.rb']
|
59
|
+
t.rcov = true
|
60
|
+
t.rcov_opts = ['--exclude', 'spec']
|
61
|
+
end
|
62
|
+
|
63
|
+
require 'rake/rdoctask'
|
64
|
+
desc "Generate documentation"
|
65
|
+
Rake::RDocTask.new do |rd|
|
66
|
+
rd.main = "README.rdoc"
|
67
|
+
rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
|
68
|
+
rd.rdoc_dir = 'rdoc'
|
69
|
+
end
|
70
|
+
|
71
|
+
begin
|
72
|
+
require 'code_stats'
|
73
|
+
CodeStats::Tasks.new
|
74
|
+
rescue LoadError
|
75
|
+
puts "Code stats not available, install it with gem install code_stats"
|
76
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'spec/rake/spectask'
|
3
|
+
task :spec => 'spec:all'
|
4
|
+
namespace(:spec) do
|
5
|
+
Spec::Rake::SpecTask.new(:all) do |t|
|
6
|
+
t.spec_opts ||= []
|
7
|
+
t.spec_opts << "-rubygems"
|
8
|
+
t.spec_opts << "--options" << "spec/spec.opts"
|
9
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'messed'
|
6
|
+
rescue LoadError
|
7
|
+
if ENV['MESSED_HOME']
|
8
|
+
require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
|
9
|
+
else
|
10
|
+
raise("no messed!")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'thor'
|
15
|
+
|
16
|
+
$root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
17
|
+
|
18
|
+
Messed::Tasks::Runner.start
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'messed'
|
6
|
+
rescue LoadError
|
7
|
+
if ENV['MESSED_HOME']
|
8
|
+
require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
|
9
|
+
else
|
10
|
+
raise("no messed!")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'thor'
|
15
|
+
|
16
|
+
class IncomingRunnerTask < Thor
|
17
|
+
|
18
|
+
method_options :detach => false
|
19
|
+
method_options :environment => "development"
|
20
|
+
desc "start [NAME]", "start an incoming instance"
|
21
|
+
def start(name = nil)
|
22
|
+
application = Messed::Booter.new(File.expand_path(File.join(File.dirname(__FILE__), '..')), options.environment)
|
23
|
+
incoming = if name.nil? and application.incoming_map.size == 1
|
24
|
+
application.incoming_map.values.first
|
25
|
+
elsif application.incoming_map.key?(name)
|
26
|
+
application.incoming_map[name]
|
27
|
+
else
|
28
|
+
raise(name ? "unable to find incoming with name #{name}" : "You have no incoming setup.")
|
29
|
+
end
|
30
|
+
|
31
|
+
IncomingRunner.new(incoming)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
IncomingRunnerTask.start
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
begin
|
5
|
+
require 'messed'
|
6
|
+
rescue LoadError
|
7
|
+
if ENV['MESSED_HOME']
|
8
|
+
require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
|
9
|
+
else
|
10
|
+
raise("no messed!")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'thor'
|
15
|
+
|
16
|
+
class WebTask < Thor
|
17
|
+
|
18
|
+
method_options :detach => false
|
19
|
+
method_options :environment => "development"
|
20
|
+
desc "start [NAME]", "start an incoming instance"
|
21
|
+
def start(name = nil)
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
IncomingRunnerTask.start
|
File without changes
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
begin
|
3
|
+
require 'messed'
|
4
|
+
rescue LoadError
|
5
|
+
if ENV['MESSED_HOME']
|
6
|
+
require File.join(ENV['MESSED_HOME'], 'lib', 'messed')
|
7
|
+
else
|
8
|
+
raise("no messed!")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class MessedSpecHolder
|
13
|
+
|
14
|
+
attr_accessor :booter, :outgoing_messages
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@booter = Messed::Booter.new(File.join(File.dirname(__FILE__), '..'))
|
18
|
+
end
|
19
|
+
|
20
|
+
def application
|
21
|
+
@booter.application
|
22
|
+
end
|
23
|
+
|
24
|
+
def process(message)
|
25
|
+
@outgoing_messages = application.process(application.message_class.new(message))
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module MessedSpecHelper
|
31
|
+
|
32
|
+
Holder = MessedSpecHolder.new
|
33
|
+
|
34
|
+
def process(message)
|
35
|
+
Holder.process(message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def outgoing_messages
|
39
|
+
Holder.outgoing_messages
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/bin/messed
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
class Messed
|
4
|
+
class Booter
|
5
|
+
|
6
|
+
include Logger::LoggingModule
|
7
|
+
|
8
|
+
attr_reader :root_directory, :environment, :application, :interface_map, :configuration, :pid
|
9
|
+
|
10
|
+
def initialize(root_directory, options = {}, &block)
|
11
|
+
if block
|
12
|
+
EMRunner.new(:detach => options[:detach], :supress_banner => options[:supress_banner]) {
|
13
|
+
setup_booter(root_directory, options)
|
14
|
+
record_pid(Process.pid)
|
15
|
+
yield self
|
16
|
+
}
|
17
|
+
else
|
18
|
+
setup_booter(root_directory, options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def setup_booter(root_directory, options)
|
23
|
+
$LOAD_PATH << File.expand_path(root_directory)
|
24
|
+
|
25
|
+
@root_directory = root_directory
|
26
|
+
@environment = options[:environment] || 'development'
|
27
|
+
|
28
|
+
load_configuration
|
29
|
+
prepare_root
|
30
|
+
setup_logger
|
31
|
+
setup_queues
|
32
|
+
setup_interfaces
|
33
|
+
setup_application
|
34
|
+
end
|
35
|
+
|
36
|
+
def record_pid(pid)
|
37
|
+
@pid = pid
|
38
|
+
end
|
39
|
+
|
40
|
+
def expand_pid_file(pid_file)
|
41
|
+
File.expand_path(pid_file, root_directory)
|
42
|
+
end
|
43
|
+
|
44
|
+
def write_pid_file(pid_file)
|
45
|
+
File.open(expand_pid_file(pid_file), 'w') {|f| f << pid} if pid_file
|
46
|
+
end
|
47
|
+
|
48
|
+
def read_pid_file(pid_file)
|
49
|
+
Integer(File.read(expand_pid_file(pid_file)))
|
50
|
+
rescue ArgumentError
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def prepare_root
|
55
|
+
FileUtils.mkdir_p(File.join(root_directory, 'log'))
|
56
|
+
FileUtils.mkdir_p(File.join(root_directory, 'tmp', 'pid'))
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_configuration
|
60
|
+
@configuration = Configuration.load_from_directory(@environment, File.expand_path(File.join(root_directory, 'config')))
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_queues
|
64
|
+
@incoming_queue = create_incoming_queue
|
65
|
+
@outgoing_queue = create_outgoing_queue
|
66
|
+
end
|
67
|
+
|
68
|
+
def setup_application
|
69
|
+
@application = Messed.new
|
70
|
+
@application.booter = self
|
71
|
+
@application.incoming = create_incoming_queue
|
72
|
+
@application.outgoing = create_outgoing_queue
|
73
|
+
@application.instance_eval(File.read(runner_file), runner_file)
|
74
|
+
end
|
75
|
+
|
76
|
+
def setup_logger
|
77
|
+
Messed::Logger.instance.setup_logger(configuration.logger || ::Logger.new(File.open(File.join(root_directory, 'log', "#{environment}.log"), File::WRONLY | File::APPEND | File::CREAT)), configuration.log_level || :debug)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.possible_interfaces(path)
|
81
|
+
booter = new(path)
|
82
|
+
booter.configuration.interfaces.names
|
83
|
+
end
|
84
|
+
|
85
|
+
def runner_file
|
86
|
+
File.join(root_directory, 'app/runner.rb')
|
87
|
+
end
|
88
|
+
|
89
|
+
def environmental_configuration_file
|
90
|
+
File.join(root_directory, "config/environments/#{environment}.rb")
|
91
|
+
end
|
92
|
+
|
93
|
+
def setup_interfaces
|
94
|
+
@interface_map = {}
|
95
|
+
configuration.interfaces.each do |name, conf|
|
96
|
+
logger.info "Setting up interface: #{name.inspect}"
|
97
|
+
@interface_map[name] = Interface.interface_from_configuration(self, name, conf)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def interface_for(name)
|
102
|
+
interface_map[name]
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_incoming_queue
|
106
|
+
Messed::Queue::Beanstalk.new(configuration.queues.incoming.tube, configuration.queues.incoming.host, configuration.queues.incoming.port)
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_outgoing_queue
|
110
|
+
Messed::Queue::Beanstalk.new(configuration.queues.outgoing.tube, configuration.queues.outgoing.host, configuration.queues.outgoing.port)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
class Messed
|
2
|
+
class Configuration
|
3
|
+
|
4
|
+
module ConfigHelper
|
5
|
+
|
6
|
+
def with(&block)
|
7
|
+
instance_eval(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.load_from_directory(environment, dir)
|
13
|
+
environments = []
|
14
|
+
Dir[File.join(dir, '*')].each do |file|
|
15
|
+
environments << file if File.directory?(file)
|
16
|
+
end
|
17
|
+
|
18
|
+
instance = new(environments, environment)
|
19
|
+
|
20
|
+
instance.instance_eval(File.read(File.join(dir, 'environment.rb')), File.join(dir, 'environment.rb'), 1)
|
21
|
+
instance.instance_eval(File.read(File.join(dir, 'environments', "#{environment}.rb")), File.join(dir, 'environments', "#{environment}.rb"), 1)
|
22
|
+
|
23
|
+
instance
|
24
|
+
end
|
25
|
+
|
26
|
+
class Interfaces
|
27
|
+
include ConfigHelper
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@interfaces = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def each(&block)
|
34
|
+
@interfaces.each(&block)
|
35
|
+
end
|
36
|
+
|
37
|
+
def names
|
38
|
+
@interfaces.keys
|
39
|
+
end
|
40
|
+
|
41
|
+
def method_missing(method, *args, &block)
|
42
|
+
@interfaces[method] ||= IndividualInterface.new
|
43
|
+
end
|
44
|
+
|
45
|
+
class IndividualInterface
|
46
|
+
|
47
|
+
include ConfigHelper
|
48
|
+
|
49
|
+
attr_accessor :adapter, :options, :status_port, :status_address, :pid_file
|
50
|
+
|
51
|
+
def initialize
|
52
|
+
@options = {}
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class Queues
|
60
|
+
include ConfigHelper
|
61
|
+
attr_reader :incoming, :outgoing
|
62
|
+
|
63
|
+
def initialize
|
64
|
+
@incoming = IndivialQueue.new
|
65
|
+
@outgoing = IndivialQueue.new
|
66
|
+
end
|
67
|
+
|
68
|
+
class IndivialQueue
|
69
|
+
include ConfigHelper
|
70
|
+
attr_accessor :host, :port, :tube
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class Application
|
76
|
+
include ConfigHelper
|
77
|
+
attr_accessor :status_port, :status_address, :pid_file
|
78
|
+
end
|
79
|
+
|
80
|
+
include ConfigHelper
|
81
|
+
|
82
|
+
attr_reader :queues, :interfaces, :application, :environment, :environments
|
83
|
+
attr_accessor :logger, :log_level
|
84
|
+
|
85
|
+
def initialize(environments, environment)
|
86
|
+
@environments, @environment = environments, environment
|
87
|
+
@queues = Queues.new
|
88
|
+
@interfaces = Interfaces.new
|
89
|
+
@application = Application.new
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Messed
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
module Processing
|
5
|
+
def self.included(target)
|
6
|
+
|
7
|
+
target.send(:class_variable_set, :@@after, []) unless target.send(:class_variable_defined?, :@@after)
|
8
|
+
target.class_eval "
|
9
|
+
|
10
|
+
def self.after_processing(t)
|
11
|
+
@@after << t
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset_processing!
|
15
|
+
@@after.each {|a| send(a)}
|
16
|
+
end
|
17
|
+
"
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Messed
|
2
|
+
class Controller
|
3
|
+
module Respond
|
4
|
+
|
5
|
+
def self.included(c)
|
6
|
+
c.instance_eval "
|
7
|
+
after_processing :clear_responses
|
8
|
+
"
|
9
|
+
end
|
10
|
+
|
11
|
+
def responses
|
12
|
+
@response ||= []
|
13
|
+
end
|
14
|
+
|
15
|
+
def clear_responses
|
16
|
+
responses.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
def say(response)
|
20
|
+
set_response(response)
|
21
|
+
end
|
22
|
+
|
23
|
+
def reply(response, options = {})
|
24
|
+
options[:to] ||= message.from
|
25
|
+
options[:from] ||= message.to
|
26
|
+
options[:in_reply_to] ||= message
|
27
|
+
set_response(response, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def whisper(response, options = {})
|
31
|
+
options[:private] = true
|
32
|
+
reply(response, options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_response(response, options = nil)
|
36
|
+
message = message_class.new
|
37
|
+
message.body = response.is_a?(Message) ? response.body : response
|
38
|
+
if options
|
39
|
+
options.each do |key, value|
|
40
|
+
message.send(:"#{key}=", value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
self.responses << message
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Messed
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
autoload :Processing, File.join('messed', 'controller', 'processing')
|
5
|
+
autoload :Respond, File.join('messed', 'controller', 'respond')
|
6
|
+
autoload :Helper, File.join('messed', 'controller', 'helper')
|
7
|
+
|
8
|
+
def self.inherited(subclass)
|
9
|
+
subclass.instance_eval "
|
10
|
+
include Messed::Controller::Helper
|
11
|
+
include Messed::Controller::Processing
|
12
|
+
include Messed::Controller::Respond
|
13
|
+
"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Messed
|
2
|
+
class EMRunner
|
3
|
+
|
4
|
+
include Logger::LoggingModule
|
5
|
+
|
6
|
+
class StatusHandler < EventMachine::Connection
|
7
|
+
|
8
|
+
attr_accessor :interface
|
9
|
+
|
10
|
+
Terminator = "\r\n"
|
11
|
+
TerminatorRegex = /\r\n/
|
12
|
+
Error = "ERROR\r\n"
|
13
|
+
|
14
|
+
def receive_data(data)
|
15
|
+
ss = StringScanner.new(data)
|
16
|
+
while part = ss.scan_until(TerminatorRegex)
|
17
|
+
if part == 'status'
|
18
|
+
send_data(interface.status)
|
19
|
+
send_data(Terminator)
|
20
|
+
else
|
21
|
+
send_data(Error)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(options, &block)
|
28
|
+
logger.info "Starting..." unless options[:supress_banner]
|
29
|
+
if options[:detach]
|
30
|
+
pid = EM.fork_reactor do
|
31
|
+
trap("INT") { EM.stop_reactor_loop }
|
32
|
+
EM.run do
|
33
|
+
EM.next_tick(&block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
Process.detach(pid)
|
37
|
+
exit(0)
|
38
|
+
else
|
39
|
+
EM.run do
|
40
|
+
EM.next_tick(&block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def quit
|
46
|
+
EM.stop; logger.info "\nStoping #{interface.name.to_s}"; exit(0)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|