sails 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,103 @@
1
+ module Sails
2
+ class Daemon
3
+ class << self
4
+ attr_accessor :options, :mode, :app_name, :pid_file
5
+
6
+ def init(opts = {})
7
+ self.app_name = Sails.config.app_name
8
+ self.mode = opts[:mode]
9
+ self.app_name = "#{Sails::Daemon.app_name}-thread" if self.mode == "thread"
10
+ self.pid_file = Sails.root.join("tmp/#{Sails::Daemon.app_name}.pid")
11
+ self.options = options
12
+ end
13
+
14
+ def read_pid
15
+ if !File.exist?(pid_file)
16
+ return nil
17
+ end
18
+
19
+ pid = File.open(pid_file).read.to_i
20
+ begin
21
+ Process.getpgid(pid)
22
+ rescue
23
+ pid = nil
24
+ end
25
+ return pid
26
+ end
27
+
28
+ def start_process(options = {})
29
+ old_pid = read_pid
30
+ if old_pid != nil
31
+ puts "Current have #{app_name} process in running on pid #{old_pid}"
32
+ return
33
+ end
34
+
35
+ # start master process
36
+ @master_pid = fork_master_process!
37
+ File.open(pid_file, "w+") do |f|
38
+ f.puts @master_pid
39
+ end
40
+
41
+ puts "Started #{app_name} on pid: #{@master_pid}"
42
+
43
+ if options[:daemon] == false
44
+ Process.waitpid(@master_pid)
45
+ end
46
+ end
47
+
48
+ def fork_master_process!
49
+ fork do
50
+ $PROGRAM_NAME = self.app_name + " [master]"
51
+ @child_pid = fork_child_process!
52
+
53
+ Signal.trap("QUIT") {
54
+ Process.kill("QUIT", @child_pid)
55
+ exit
56
+ }
57
+
58
+ Signal.trap("USR2") {
59
+ Process.kill("USR2", @child_pid)
60
+ }
61
+
62
+ loop do
63
+ sleep 1
64
+ begin
65
+ Process.getpgid(@child_pid)
66
+ rescue Errno::ESRCH => e
67
+ # puts "Child not found, will restart..."
68
+ @child_pid = fork_child_process!
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def fork_child_process!
75
+ fork do
76
+ $PROGRAM_NAME = self.app_name
77
+ Sails.start!(self.mode)
78
+
79
+ Signal.trap("USR2") {
80
+ # TODO: reload Sails in current process
81
+ exit
82
+ }
83
+ end
84
+ end
85
+
86
+ def stop_process
87
+ pid = read_pid
88
+ if pid == nil
89
+ puts "#{app_name} process not found, pid #{pid}"
90
+ return
91
+ end
92
+
93
+ print "Stopping #{app_name} with pid: #{pid}..."
94
+ begin
95
+ Process.kill("QUIT", pid)
96
+ ensure
97
+ File.delete(pid_file)
98
+ end
99
+ puts " [Done]"
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,56 @@
1
+ module Sails
2
+ module Service
3
+ # Like ActionController::Base
4
+ class Base
5
+ include ActiveSupport::Callbacks
6
+
7
+ define_callbacks :action
8
+
9
+ set_callback :action, :before do |object|
10
+ # TODO: only reload on files changed
11
+ Sails.reload!
12
+ end
13
+
14
+ set_callback :action, :after do |object|
15
+ ActiveRecord::Base.clear_active_connections! if defined?(ActiveRecord::Base)
16
+ end
17
+
18
+ class << self
19
+ def internal_methods
20
+ controller = self.superclass
21
+ controller.public_instance_methods(true)
22
+ end
23
+
24
+ def action_methods
25
+ @action_methods ||= begin
26
+ # All public instance methods of this class, including ancestors
27
+ methods = (public_instance_methods(true) -
28
+ # Except for public instance methods of Base and its ancestors
29
+ internal_methods +
30
+ # Be sure to include shadowed public instance methods of this class
31
+ public_instance_methods(false)).uniq.map { |x| x.to_s }
32
+
33
+ # Clear out AS callback method pollution
34
+ Set.new(methods.reject { |method| method =~ /_one_time_conditions/ })
35
+ end
36
+ end
37
+ end
38
+
39
+ # Raise a Sails::Service::Exception (Thrift::Exception)
40
+ # if you want custom error you can override this method in you ApplicationService
41
+ def raise_error(code, msg = nil)
42
+ raise Exception.new(code: code, message: msg)
43
+ end
44
+
45
+ def action_methods
46
+ self.class.action_methods
47
+ end
48
+
49
+ # Sails.logger
50
+ # You can use this method in app/services
51
+ def logger
52
+ Sails.logger
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,22 @@
1
+ module Sails
2
+ module Service
3
+ # Thrift Exception
4
+ class Exception < ::Thrift::Exception
5
+ include ::Thrift::Struct, ::Thrift::Struct_Union
6
+ CODE = 1
7
+ MESSAGE = 2
8
+
9
+ FIELDS = {
10
+ CODE => {:type => ::Thrift::Types::I32, :name => 'code'},
11
+ MESSAGE => {:type => ::Thrift::Types::STRING, :name => 'message'}
12
+ }
13
+
14
+ def struct_fields; FIELDS; end
15
+
16
+ def validate
17
+ end
18
+
19
+ ::Thrift::Struct.generate_accessors self
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,60 @@
1
+ module Sails
2
+ module Service
3
+ class Interface
4
+ attr_accessor :services
5
+
6
+ def initialize
7
+ @services = []
8
+ Dir["#{Sails.root.join("app/services")}/*_service.rb"].each do |f|
9
+ if File.basename(f) =~ /^(.*)_service.rb$/
10
+ require f
11
+ mtd = $1.dup
12
+ klass_name = "#{mtd.camelize}Service"
13
+ @services << klass_name.constantize.new
14
+ end
15
+ end
16
+ define_service_methods!
17
+ end
18
+
19
+ private
20
+ def define_service_methods!
21
+ @services.each do |instance|
22
+ instance.action_methods.each do |method_name|
23
+ self.class.send(:define_method, method_name) do |*args, &block|
24
+ run_action(instance, method_name, *args, &block)
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def run_action(instance, method_name, *args, &block)
31
+ instance.run_callbacks :action do
32
+ time = Time.now.to_f
33
+
34
+ Sails.logger.info "\nProcessing by \"#{method_name}\" at #{Time.now.to_s}" unless Sails.env.test?
35
+ Sails.logger.info " Parameters: { #{args.map(&:inspect).join(', ')} }" unless Sails.env.test?
36
+
37
+ begin
38
+ res = instance.send(method_name, *args, &block)
39
+ status = "Completed"
40
+ return res
41
+ rescue ActiveRecord::RecordNotFound => e
42
+ status = "Not Found"
43
+ instance.raise_error(404)
44
+ rescue Thrift::Exception => e
45
+ status = "Failed #{e.try(:code)}"
46
+ raise e
47
+ rescue => e
48
+ status = "Error 500"
49
+ Sails.logger.info "\"#{method_name}\" error : #{e.inspect}\n\n"
50
+ Sails.logger.info %Q(backtrace: #{e.backtrace.join("\n")}\n)
51
+ instance.raise_error(500)
52
+ ensure
53
+ elapsed = format('%.3f', (Time.now.to_f - time) * 1000)
54
+ Sails.logger.info "#{status} in (#{elapsed}ms).\n\n" unless Sails.env.test?
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
data/lib/sails/service.rb CHANGED
@@ -1,77 +1,10 @@
1
1
  module Sails
2
- class Service
3
- include ActiveSupport::Callbacks
4
- define_callbacks :action
5
-
6
- set_callback :action, :before do |object|
7
- end
8
-
9
- set_callback :action, :after do |object|
10
- ActiveRecord::Base.clear_active_connections! if defined?(ActiveRecord::Base)
11
- end
12
-
13
- def method_missing(method_name, *args, &block)
14
- run_callbacks :action do
15
- time = Time.now.to_f
16
-
17
- Sails.logger.info "\nProcessing by \"#{method_name}\" at #{Time.now.to_s}" unless Sails.env.test?
18
- Sails.logger.info " Parameters: { #{args.map(&:inspect).join(', ')} }" unless Sails.env.test?
19
-
20
- begin
21
- res = interface.send(method_name, *args, &block)
22
- status = "Completed"
23
- return res
24
- rescue ActiveRecord::RecordNotFound => e
25
- status = "Not Found"
26
- interface.raise_error(-1004)
27
- rescue ThriftServer::OperationFailed => e
28
- status = "Failed #{e.code}"
29
- raise e
30
- rescue => e
31
- status = "Error 500"
32
- Sails.logger.info "\"#{method_name}\" error : #{e.inspect}\n\n"
33
- Sails.logger.info %Q(backtrace: #{e.backtrace.join("\n")}\n)
34
- interface.raise_error(-1000)
35
- ensure
36
- elapsed = format('%.3f', (Time.now.to_f - time) * 1000)
37
- Sails.logger.info "#{status} in (#{elapsed}ms).\n\n" unless Sails.env.test?
38
- end
39
- end
40
- end
41
-
42
- def args
43
- @args ||= []
44
- end
45
-
46
- def initialize(*array)
47
- args.concat array
48
- end
49
-
50
- class Interface
51
- Dir["#{Sails.root.join("app/services")}/*_service.rb"].each do |f|
52
- next if 'base_service.rb' == File.basename(f)
53
- if File.basename(f) =~ /^(.*)_service.rb$/
54
- require f
55
- mtd = $1.dup
56
- klass_name = "#{mtd.camelize}Service"
57
- include klass_name.constantize
58
- end
59
- end
60
-
61
- def raise_error code, msg = nil
62
- raise ThriftServer::OperationFailed.new(
63
- code: code,
64
- message: msg
65
- )
66
- end
67
-
68
- def logger
69
- Sails.logger
70
- end
71
- end
72
-
73
- def interface
74
- @interface ||= Interface.new
75
- end
2
+ module Service
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Base
6
+ autoload :Config
7
+ autoload :Exception
8
+ autoload :Interface
76
9
  end
77
- end
10
+ end
@@ -7,11 +7,6 @@ Dir.glob('lib/tasks/*.rake').each { |r| import r }
7
7
 
8
8
  task :default => :test
9
9
 
10
- task :console do
11
- puts "Starting thrift-server console..."
12
- system "pry -I config/application.rb -r ./config/application.rb"
13
- end
14
-
15
10
  task :gen do
16
11
  puts "Generating thrift code..."
17
12
  system 'thrift \
@@ -1,6 +1,8 @@
1
- module ApplicationService
2
- extend ActiveSupport::Concern
3
-
1
+ class ApplicationService < Sails::Service::Base
4
2
  # def require_user!(user_id, access_token)
5
3
  # end
4
+
5
+ # def raise_error(code, msg = nil)
6
+ # raise YouCustomThriftException.new(code: code, message: msg)
7
+ # end
6
8
  end
@@ -8,9 +8,15 @@ require "app/services/handler"
8
8
  module Sails
9
9
  config.app_name = '<%= app_name %>'
10
10
  # Thrift Configs
11
- config.thrift_host = '127.0.0.1'
12
- config.thrift_port = 4000
13
- config.thrift_processor = Thrift::<%= app_name.capitalize %>::Processor
11
+ config.port = 4000
12
+
13
+ # Thrift protocol allows: :binary, :compact, default: :binary
14
+ # config.protocol = :binary
15
+
16
+ # Number of threads, default: 20
17
+ # config.thread_size = 20
18
+
19
+ config.processor = Thrift::<%= app_name.capitalize %>::Processor
14
20
 
15
21
  # config.autoload_paths += %W(app/workers)
16
22
 
@@ -0,0 +1,3 @@
1
+ module Sails
2
+ config.cache_classes = false
3
+ end
@@ -0,0 +1,3 @@
1
+ module Sails
2
+ config.cache_classes = true
3
+ end
@@ -0,0 +1,3 @@
1
+ module Sails
2
+ config.cache_classes = false
3
+ end
data/lib/sails/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Sails
2
2
  def self.version
3
- "0.1.0"
3
+ "0.1.1"
4
4
  end
5
5
  end
data/lib/sails.rb CHANGED
@@ -1,7 +1,40 @@
1
- require "sails/version"
2
- require "sails/base"
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'active_support/all'
4
+ require 'i18n'
5
+ require 'thrift'
6
+ require 'yaml'
3
7
  require "sails/rails"
4
- require "sails/cli"
5
- require "sails/service"
8
+ require "sails/base"
6
9
 
7
- Sails.init()
10
+ # Sails
11
+ #
12
+ # You can custom Sails configs in config/application.rb
13
+ #
14
+ # module Sails
15
+ # config.app_name = 'you_app_name'
16
+ # config.thrift.port = 7075
17
+ # config.thrift.processor = Thrift::YouAppName::Processor
18
+ #
19
+ # # Thrift Protocols can be use [:binary, :compact, :json]
20
+ # # http://jnb.ociweb.com/jnb/jnbJun2009.html#protocols
21
+ # config.thrift.procotol = :binary
22
+ #
23
+ # config.autoload_paths += %W(app/workers)
24
+ #
25
+ # config.i18n.default_locale = 'zh-CN'
26
+ #
27
+ # # cache store
28
+ # config.cache_store = [:dalli_store, '127.0.0.1' }]
29
+ # end
30
+ #
31
+ module Sails
32
+ extend ActiveSupport::Autoload
33
+
34
+ autoload :Config
35
+ autoload :Version
36
+ autoload :Service
37
+ autoload :CLI
38
+ autoload :Daemon
39
+ autoload :Console
40
+ end
data/sails.gemspec CHANGED
@@ -6,11 +6,11 @@ Gem::Specification.new do |s|
6
6
  s.name = "sails"
7
7
  s.version = Sails.version
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Jason Lee"]
10
- s.email = ["huacnlee@gmail.com"]
9
+ s.authors = ["Jason Lee", "P.S.V.R", "wxianfeng", "sapronlee","qhwa"]
10
+ s.email = ["huacnlee@gmail.com", "pmq2001@gmail.com", "wang.fl1429@gmail.com", "sapronlee@gmail.com","qhwa@163.com"]
11
11
  s.homepage = "https://github.com/huacnlee/sails"
12
- s.summary = %q{Sails, create Thrift Server use like Rails}
13
- s.description = %q{Sails, create Thrift Server use like Rails}
12
+ s.summary = %q{Sails, Help you to create Rails style Thrift Server}
13
+ s.description = %q{Sails, Help you to create Rails style Thrift Server}
14
14
  s.files = `git ls-files`.split("\n")
15
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
16
  s.executables = ["sails"]
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Sails::CLI' do
4
+ let(:cli) { Sails::CLI.new }
5
+ describe '.start' do
6
+ it { expect(cli).to respond_to(:start) }
7
+ it {
8
+ expect(Sails::Daemon).to receive(:init)
9
+ expect(Sails::Daemon).to receive(:start_process)
10
+ cli.start
11
+ }
12
+ end
13
+
14
+ describe '.stop' do
15
+ it { expect(cli).to respond_to(:stop) }
16
+ it {
17
+ expect(Sails::Daemon).to receive(:init)
18
+ expect(Sails::Daemon).to receive(:stop_process)
19
+ cli.stop
20
+ }
21
+ end
22
+
23
+ describe '.restart' do
24
+ it { expect(cli).to respond_to(:restart) }
25
+ it {
26
+ # expect(Sails::Daemon).to receive(:init)
27
+ expect(Sails::Daemon).to receive(:stop_process)
28
+ expect(Sails::Daemon).to receive(:start_process)
29
+ cli.restart
30
+ }
31
+ end
32
+
33
+ describe '.new' do
34
+ it { expect(cli).to respond_to(:new) }
35
+ end
36
+
37
+ describe '.console' do
38
+ it { expect(cli).to respond_to(:console) }
39
+ end
40
+
41
+ describe '.version' do
42
+ it { expect(cli).to respond_to(:version) }
43
+ end
44
+ end
@@ -1 +1,28 @@
1
1
  # Logfile created on 2014-12-08 13:02:26 +0800 by logger.rb/44203
2
+ Cache clear: flushing all keys
3
+ Dalli::Server#connect 127.0.0.1:11211
4
+ Cache clear: flushing all keys
5
+ Cache clear: flushing all keys
6
+ Cache clear: flushing all keys
7
+ Cache clear: flushing all keys
8
+ Cache clear: flushing all keys
9
+ Cache clear: flushing all keys
10
+ Cache clear: flushing all keys
11
+ Cache clear: flushing all keys
12
+ Cache clear: flushing all keys
13
+ Cache clear: flushing all keys
14
+ Cache clear: flushing all keys
15
+ Cache clear: flushing all keys
16
+ Cache clear: flushing all keys
17
+ Cache clear: flushing all keys
18
+ Cache clear: flushing all keys
19
+ Cache clear: flushing all keys
20
+ Cache clear: flushing all keys
21
+ Cache clear: flushing all keys
22
+ Cache clear: flushing all keys
23
+ Cache clear: flushing all keys
24
+ Cache clear: flushing all keys
25
+ Cache clear: flushing all keys
26
+ Cache clear: flushing all keys
27
+ Cache clear: flushing all keys
28
+ Cache clear: flushing all keys
@@ -0,0 +1,5 @@
1
+ describe 'Rails' do
2
+ it { expect(Rails.logger).to eq Sails.logger }
3
+ it { expect(Rails.cache).to eq Sails.cache }
4
+ it { expect(Rails.env).to eq Sails.env }
5
+ end
@@ -0,0 +1,70 @@
1
+ require "spec_helper"
2
+
3
+ describe 'Sails' do
4
+ it { expect(Sails.version).not_to be_nil }
5
+
6
+ describe '#root' do
7
+ it 'should be a Pathname class' do
8
+ expect(Sails.root).to be_a(Pathname)
9
+ end
10
+
11
+ it 'should support Sails.root.join' do
12
+ expect(Sails.root.join("aaa").to_s).to eq File.join(Dir.pwd, "spec/dummy/aaa")
13
+ end
14
+
15
+ it 'should work' do
16
+ expect(Sails.root.to_s).to eq File.join(Dir.pwd, "spec/dummy")
17
+ end
18
+ end
19
+
20
+ describe '#logger' do
21
+ it 'should be a Logger class' do
22
+ expect(Sails.logger).to be_a(Logger)
23
+ end
24
+ end
25
+
26
+ describe '#config' do
27
+ it 'should work' do
28
+ expect(Sails.config).to be_a(Hash)
29
+ expect(Sails.config.autoload_paths).to be_a(Array)
30
+ end
31
+
32
+ describe 'Real config' do
33
+ it { expect(Sails.config.app_name).to eq 'hello' }
34
+ it { expect(Sails.config.host).to eq '1.1.1.1' }
35
+ it { expect(Sails.config.port).to eq 1000 }
36
+ it { expect(Sails.config.protocol).to eq :binary }
37
+ it { expect(Sails.config.thread_size).to eq 20 }
38
+ it { expect(Sails.config.i18n.default_locale).to eq :'zh-TW' }
39
+ it { expect(Sails.config.autoload_paths).to include("app/bar") }
40
+ end
41
+ end
42
+
43
+ describe '#cache' do
44
+ it { expect(Sails.cache).to be_a(ActiveSupport::Cache::DalliStore) }
45
+ it { expect(Sails.cache).to respond_to(:read, :write, :delete, :clear) }
46
+ end
47
+
48
+ describe '#thrift_protocol_class' do
49
+ it 'should work' do
50
+ allow(Sails.config).to receive(:protocol).and_return(:binary)
51
+ expect(Sails.thrift_protocol_class).to eq ::Thrift::BinaryProtocolFactory
52
+ allow(Sails.config).to receive(:protocol).and_return(:compact)
53
+ expect(Sails.thrift_protocol_class).to eq ::Thrift::CompactProtocolFactory
54
+ allow(Sails.config).to receive(:protocol).and_return(:json)
55
+ expect(Sails.thrift_protocol_class).to eq ::Thrift::JsonProtocolFactory
56
+ allow(Sails.config).to receive(:protocol).and_return(:xxx)
57
+ expect(Sails.thrift_protocol_class).to eq ::Thrift::BinaryProtocolFactory
58
+ end
59
+ end
60
+
61
+ describe '#reload!' do
62
+ it 'should work' do
63
+ s1 = Sails.service
64
+ Sails.reload!
65
+ expect(Sails.service).not_to eq s1
66
+ # TODO: test reload autoload_paths
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,38 @@
1
+ require "spec_helper"
2
+
3
+ describe 'Service' do
4
+ class SimpleService < Sails::Service::Base
5
+ def foo
6
+ end
7
+
8
+ def bar
9
+ end
10
+
11
+ private
12
+ def dar
13
+ end
14
+ end
15
+
16
+ let(:simple) { SimpleService.new }
17
+
18
+ describe '.raise_error' do
19
+ it { expect(simple).to respond_to(:raise_error) }
20
+ it {
21
+ expect { simple.raise_error(11,'foo') }.to raise_error do |error|
22
+ expect(error).to be_a(Sails::Service::Exception)
23
+ expect(error.code).to eq 11
24
+ expect(error.message).to eq 'foo'
25
+ end
26
+ }
27
+ end
28
+
29
+ describe '.action_methods' do
30
+ it { expect(simple.action_methods).to include("foo", "bar") }
31
+ it { expect(simple.action_methods.size).to eq 2 }
32
+ it { expect(simple.action_methods).not_to include("dar") }
33
+ end
34
+
35
+ describe '.logger' do
36
+ it { expect(simple.logger).to eq Sails.logger }
37
+ end
38
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,26 @@
1
1
  require_relative "../lib/sails"
2
2
 
3
3
  # Force set Sails root to spec/dummy
4
- Sails.root = File.expand_path("../dummy", __FILE__)
4
+ Sails.root = File.expand_path("../dummy", __FILE__)
5
+ $LOAD_PATH.unshift Sails.root
6
+
7
+ # for test Sails config
8
+ module Sails
9
+ config.app_name = 'hello'
10
+ config.host = '1.1.1.1'
11
+ config.port = 1000
12
+ config.i18n.default_locale = 'zh-TW'
13
+ config.autoload_paths += %W(app/bar)
14
+ config.cache_store = [:dalli_store, '127.0.0.1']
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+
19
+ config.before(:each) do
20
+ end
21
+
22
+ config.after(:each) do
23
+ end
24
+
25
+ config.raise_errors_for_deprecations!
26
+ end