sails 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f659284fee2c294ceb15bf368ea80f61c8331fc3
4
- data.tar.gz: 0f52d780eb04bafa7b4a63ef9d5460fce2ea8c2a
3
+ metadata.gz: 9910e5d27ef628ca22aec968edd2ed2a94604295
4
+ data.tar.gz: 6e72d2491ad1950a6a2e6946205a6ac84e266914
5
5
  SHA512:
6
- metadata.gz: 717ac7ec1138af2afe82d8460af64c0e5cafe6573fbe8e1b198124823074eaceba4514a93e9ca1da316c22b4eb9ec621468c53914f6721df3b583d664973619d
7
- data.tar.gz: 3aa695a566367311681b0439a7e16c48171c2595b228b3775411139cd6583f88f08518a1319e39f4dc77121e4234ba42c024d29a7188616d76cf39e5b05d42ba
6
+ metadata.gz: 91c9dc674800da1fcb081bafa44438b5a673f68300df5ddbfdbc207b1c216de6354972a9dcb9866db5af245bf18dbb2d51b983b85c9c89c53e52768116561840
7
+ data.tar.gz: df6d3b9110cf3d8c3c71e31ae5c0f0c9e0744b2cd6826dd98517356b0e8b2835637f5565904e186e292aa118d33d8df7d59a7326280ec5ad1e7ee44688cd9c7e
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.1.4
5
+
6
+ script: bundle exec rspec spec
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ ## 0.1.1
2
+
3
+ - Add `sails s`, `sails c` commands.
4
+ - Refactor service layer, use class to instead module.
5
+ - Support to custom Thrift protocol with `config.protocol = :binary`.
6
+ - Fix ThriftServer::OperationFailed not found error.
7
+ - Implement Master Process to manage and protect Child Process, keep it running/restart/stop, like Unicorn.
8
+ - Add Sails.reload! to reload cache classes.
9
+ - Sails console start with IRB class, and support `reload!`,`service` methods in console.
10
+
11
+ ## 0.1.0 / 2014-12-9
12
+
13
+ - First version release.
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+ gem 'dalli'
4
5
  gem 'rspec'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sails (0.1.0)
4
+ sails (0.1.1)
5
5
  activesupport (>= 3.2.0)
6
6
  thor
7
7
  thrift (>= 0.9.0)
@@ -15,6 +15,7 @@ GEM
15
15
  minitest (~> 5.1)
16
16
  thread_safe (~> 0.1)
17
17
  tzinfo (~> 1.1)
18
+ dalli (2.7.1)
18
19
  diff-lcs (1.2.5)
19
20
  i18n (0.6.11)
20
21
  json (1.8.1)
@@ -41,5 +42,6 @@ PLATFORMS
41
42
  ruby
42
43
 
43
44
  DEPENDENCIES
45
+ dalli
44
46
  rspec
45
47
  sails!
data/README.md CHANGED
@@ -3,17 +3,34 @@ Sails
3
3
 
4
4
  Sails, create [Thrift](thrift.apache.org) app server like Rails.
5
5
 
6
+ [![Build Status](https://travis-ci.org/huacnlee/sails.svg)](https://travis-ci.org/huacnlee/sails) [![Gem Version](https://badge.fury.io/rb/sails.svg)](http://badge.fury.io/rb/sails)
7
+
8
+ ## Features
9
+
10
+ - Rails style Thrift server;
11
+ - Nonblocking mode;
12
+ - I18n support;
13
+
6
14
  ## Installation
7
15
 
8
- ```
16
+ ```bash
9
17
  $ gem install sails
18
+ $ sails -h
19
+ ENV: development
20
+ Commands:
21
+ sails help [COMMAND] # Describe available commands or one specific command
22
+ sails new APP_NAME # Create a project
23
+ sails restart # Restart Thrift server
24
+ sails start # Start Thrift server
25
+ sails stop # Stop Thrift server
26
+ sails version # Show Sails version
10
27
  ```
11
28
 
12
29
  ## Usage
13
30
 
14
31
  ### Create new project
15
32
 
16
- ```
33
+ ```bash
17
34
  $ sails new foo
18
35
  $ cd foo
19
36
  $ sails start
@@ -27,7 +44,36 @@ You can edit Thrift IDL in `app_name.thrift`, and then generate it to ruby sourc
27
44
  $ rake gen
28
45
  ```
29
46
 
47
+ ## Client Connect
48
+
49
+ ```ruby
50
+ require "app/services/gen-rb/you_app_name"
51
+ @transport ||= Thrift::FramedTransport.new(::Thrift::Socket.new('127.0.0.1', 4000, 10))
52
+ @protocol ||= Thrift::BinaryProtocol.new(@transport)
53
+ @client ||= Thrift::YouAppName::Client.new(@protocol)
54
+ @transport.open()
55
+ puts @client.ping()
56
+ => Ping pong
57
+ ```
58
+
59
+ ## Deploy
60
+
61
+ ```
62
+ $ sails s --daemon
63
+ $ ps aux
64
+ jason 2408 0.1 0.2 2648176 13532 s003 S 12:14下午 0:00.02 you_sails_app
65
+ jason 2407 0.0 0.0 2604916 1016 s003 S 12:14下午 0:00.00 you_sails_app [master]
66
+ $ sails restart
67
+ $ sails stop
68
+ ```
30
69
 
31
70
  ## API Documents
32
71
 
33
- http://rdoc.info/github/huacnlee/sails
72
+ http://www.rubydoc.info/github/huacnlee/sails
73
+
74
+
75
+ ## TODO
76
+
77
+ - [ ] Reload without restart;
78
+ - [ ] Scaffold generator;
79
+ - [X] Multi processes;
data/lib/sails/base.rb CHANGED
@@ -1,38 +1,71 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
- require 'active_support/all'
4
- require 'i18n'
5
- require 'thrift'
6
- require 'yaml'
7
-
8
1
  Bundler.require()
9
2
 
10
3
  module Sails
11
4
  extend ActiveSupport::Autoload
5
+
6
+ autoload :Config
12
7
 
13
- class Config
14
- include ActiveSupport::Configurable
15
- end
16
-
8
+ # Sails.config
9
+ #
10
+ # Configs with Sails
11
+ # For example:
12
+ #
13
+ # Sails.config.app_name
14
+ # # => returns "You App Name"
15
+ #
16
+ # Sails.config.autoload_paths
17
+ # # => returns ['app/models','app/models/concerns', 'app/workers', 'app/services'...]
18
+ #
19
+ # Sails.config.cache_store = [:dalli_store, '127.0.0.1', { pool_size: 100 }]
20
+ # Sails.config.i18n.default_locale = 'zh-CN'
21
+ #
17
22
  def self.config
18
23
  return @config if defined?(@config)
19
24
  @config = Config.new.config
20
- @config.app_name = "Sails"
21
- @config.cache_store = [:memory_store]
22
- @config.autoload_paths = %W(app/models app/models/concerns app/workers app/services app/services/concerns lib)
23
- @config.i18n = I18n
24
- @config.i18n.load_path += Dir[Sails.root.join('config', 'locales', '*.{rb,yml}').to_s]
25
- @config.i18n.default_locale = :en
26
- @config.thrift_processor = nil
27
- @config
28
25
  end
29
26
 
27
+ # Sails.cache
28
+ #
29
+ # An abstract cache store class. There are multiple cache store
30
+ # implementations, each having its own additional features. See the classes
31
+ # under the ActiveSupport::Cache module, e.g.
32
+ # ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most
33
+ # popular cache store for large production websites.
34
+ #
35
+ # Some implementations may not support all methods beyond the basic cache
36
+ # methods of +fetch+, +write+, +read+, +exist?+, and +delete+.
37
+ #
38
+ # ActiveSupport::Cache::Store can store any serializable Ruby object.
39
+ #
40
+ # Sails.cache.read('city') # => nil
41
+ # Sails.cache.write('city', "Duckburgh")
42
+ # Sails.cache.read('city') # => "Duckburgh"
43
+ #
44
+ # Keys are always translated into Strings and are case sensitive. When an
45
+ # object is specified as a key and has a +cache_key+ method defined, this
46
+ # method will be called to define the key. Otherwise, the +to_param+
47
+ # method will be called. Hashes and Arrays can also be used as keys. The
48
+ # elements will be delimited by slashes, and the elements within a Hash
49
+ # will be sorted by key so they are consistent.
50
+ #
51
+ # Sails.cache.read('city') == Sails.cache.read(:city) # => true
52
+ #
53
+ # Nil values can be cached.
30
54
  def self.cache
31
55
  return @cache if defined?(@cache)
32
56
  @cache = ActiveSupport::Cache.lookup_store(self.config.cache_store)
33
57
  end
34
58
 
35
59
  # Sails.root
60
+ #
61
+ # This method returns a Pathname object which handles paths starting with a / as absolute (starting from the root of the filesystem). Compare:
62
+ #
63
+ # For example:
64
+ # >> Sails.root
65
+ # => #<Pathname:/some/path/to/project>
66
+ # >> Sails.root + "file"
67
+ # => #<Pathname:/some/path/to/project/file>
68
+ #
36
69
  def self.root
37
70
  @root ||= Pathname.new(Dir.pwd)
38
71
  end
@@ -41,11 +74,30 @@ module Sails
41
74
  @root = Pathname.new(root)
42
75
  end
43
76
 
44
- # Sails.env.development?
77
+ # Sails.env
78
+ #
79
+ # returns a string representing the current Sails environment.
80
+ # This will read from ENV['RAILS_ENV'] like Rails
81
+ #
82
+ # For example:
83
+ #
84
+ # Sails.env # in development mode
85
+ # => "development"
86
+ # Sails.env.development?
87
+ # => true
88
+ #
45
89
  def self.env
46
90
  @env ||= ActiveSupport::StringInquirer.new(ENV['RAILS_ENV'].presence || 'development')
47
91
  end
48
92
 
93
+ # Sails.logger
94
+ #
95
+ # returns a Logger class
96
+ # For example:
97
+ #
98
+ # Sails.logger.info "Hello world"
99
+ # Sails.logger.error "Hello world"
100
+ #
49
101
  def self.logger
50
102
  return @logger if defined?(@logger)
51
103
  @logger = Logger.new(File.join(Sails.root, "log/#{self.env}.log"))
@@ -56,21 +108,6 @@ module Sails
56
108
  @logger
57
109
  end
58
110
 
59
- def self.stdout_logger
60
- return @stdout_logger if defined?(@stdout_logger)
61
- @stdout_logger = Logger.new(STDOUT)
62
- @stdout_logger.formatter = proc { |severity, datetime, progname, msg|
63
- "#{msg}\n"
64
- }
65
- @stdout_logger
66
- end
67
-
68
- def self.load_initialize
69
- Dir["#{Sails.root}/config/initializers/*.rb"].each do |f|
70
- require f
71
- end
72
- end
73
-
74
111
  def self.init
75
112
  $:.unshift self.root.join("lib")
76
113
  # init root
@@ -80,7 +117,7 @@ module Sails
80
117
 
81
118
  ActiveSupport::Dependencies.autoload_paths += Sails.config.autoload_paths
82
119
 
83
- env_file = self.root.join('config/environments/',Sails.env)
120
+ env_file = self.root.join('config/environments/',Sails.env + ".rb")
84
121
  if File.exist?(env_file)
85
122
  require env_file
86
123
  end
@@ -93,31 +130,80 @@ module Sails
93
130
  @inited = true
94
131
  end
95
132
 
133
+ # Sails.service
134
+ #
135
+ # return a instance of Sails Service layer
136
+ #
137
+ # for example:
138
+ #
139
+ # class UsersService < Sails::Service::Base
140
+ # def check_name_exist?(name)
141
+ # User.check_name_exist?(name)
142
+ # end
143
+ # end
144
+ #
145
+ # class UsersServiceTest
146
+ # def test_check_name_exist?
147
+ # assert_equal(Sails.service.check_name_exist?(name), true)
148
+ # end
149
+ # end
150
+ #
151
+ def self.service
152
+ @service ||= Sails::Service::Interface.new
153
+ end
154
+
155
+ # Force reload Sails cache classes in config.autoload_paths
156
+ def self.reload!(opts = {})
157
+ force = opts[:force] || false
158
+ if force || config.cache_classes == false
159
+ @service = nil
160
+ ActiveSupport::Dependencies.clear
161
+ reload_server!
162
+ end
163
+ end
164
+
165
+ def self.reload_server!
166
+ if @server
167
+ new_processor = config.processor.new(self.service)
168
+ @server.instance_variable_set(:@processor, new_processor)
169
+ end
170
+ end
171
+
96
172
  def self.start!(type)
97
- if type == "thread"
173
+ @server_type = type
174
+ if @server_type == "thread"
98
175
  start_thread_pool_server!
99
176
  else
100
177
  start_non_blocking_server!
101
178
  end
102
179
  end
103
-
104
- def self.service
105
- @service ||= Sails::Service.new
180
+
181
+ def self.thrift_protocol_class
182
+ case config.protocol
183
+ when :compact
184
+ return ::Thrift::CompactProtocolFactory
185
+ when :json
186
+ return ::Thrift::JsonProtocolFactory
187
+ else
188
+ return ::Thrift::BinaryProtocolFactory
189
+ end
106
190
  end
107
191
 
192
+ # Start Thrift Server with Threaded mode
193
+ #
108
194
  def self.start_thread_pool_server!
109
- transport = ::Thrift::ServerSocket.new(nil, config.thrift_thread_port)
195
+ transport = ::Thrift::ServerSocket.new(nil, config.thread_port)
110
196
  transport_factory = ::Thrift::BufferedTransportFactory.new
111
- protocol_factory = ::Thrift::BinaryProtocolFactory.new
112
- processor = config.thrift_processor.new(self.service)
113
- server = ::Thrift::ThreadPoolServer.new(processor, transport, transport_factory, protocol_factory, Setting.pool_size)
197
+ protocol_factory = thrift_protocol_class.new
198
+ processor = config.processor.new(self.service)
199
+ @server = ::Thrift::ThreadPoolServer.new(processor, transport, transport_factory, protocol_factory, config.thread_size)
114
200
 
115
201
  puts "Boot on: #{Sails.root}"
116
202
  puts "[#{Time.now}] Starting the Sails with ThreadPool size: #{Setting.pool_size}..."
117
- puts "serve: #{config.thrift_host}:#{config.thrift_thread_port}"
203
+ puts "serve: 127.0.0.1:#{config.thread_port}"
118
204
 
119
205
  begin
120
- server.serve
206
+ @server.serve
121
207
  rescue => e
122
208
  puts "Start thrift server exception! \n #{e.inspect}"
123
209
  puts e.backtrace
@@ -129,19 +215,21 @@ module Sails
129
215
  end
130
216
  end
131
217
 
218
+ # Start Thrift Server with Event drive mode
132
219
  def self.start_non_blocking_server!
133
- transport = ::Thrift::ServerSocket.new(nil, config.thrift_port)
220
+ transport = ::Thrift::ServerSocket.new(nil, config.port)
134
221
  transport_factory = ::Thrift::FramedTransportFactory.new
135
- protocol_factory = ::Thrift::BinaryProtocolFactory.new
136
- processor = config.thrift_processor.new(self.service)
137
- server = ::Thrift::NonblockingServer.new(processor, transport, transport_factory)
222
+ protocol_factory = thrift_protocol_class.new
223
+ processor = config.processor.new(self.service)
224
+ @server = ::Thrift::NonblockingServer.new(processor, transport, transport_factory, protocol_factory, config.thread_size)
138
225
 
139
226
  puts "Boot on: #{Sails.root}"
140
227
  puts "[#{Time.now}] Starting the Sails with NonBlocking..."
141
- puts "serve: #{config.thrift_host}:#{config.thrift_port}"
228
+ puts "Protocol: #{thrift_protocol_class.name}"
229
+ puts "serve: 127.0.0.1:#{config.port}"
142
230
 
143
231
  begin
144
- server.serve
232
+ @server.serve
145
233
  rescue => e
146
234
  puts "Start thrift server exception! \n #{e.inspect}"
147
235
  puts e.backtrace
@@ -152,4 +240,22 @@ module Sails
152
240
  end
153
241
  end
154
242
  end
155
- end
243
+
244
+ private
245
+ def self.stdout_logger
246
+ return @stdout_logger if defined?(@stdout_logger)
247
+ @stdout_logger = Logger.new(STDOUT)
248
+ @stdout_logger.formatter = proc { |severity, datetime, progname, msg|
249
+ "#{msg}\n"
250
+ }
251
+ @stdout_logger
252
+ end
253
+
254
+ def self.load_initialize
255
+ Dir["#{Sails.root}/config/initializers/*.rb"].each do |f|
256
+ require f
257
+ end
258
+ end
259
+ end
260
+
261
+ Sails.init()
data/lib/sails/cli.rb CHANGED
@@ -2,76 +2,12 @@ require 'thor'
2
2
  require 'sails/version'
3
3
 
4
4
  module Sails
5
- class ThreadDaemon
6
- class << self
7
- attr_accessor :options, :mode, :app_name, :pid_file
8
-
9
- def init(opts = {})
10
- self.app_name = Sails.config.app_name
11
- self.mode = opts[:mode]
12
- self.app_name = "#{ThreadDaemon.app_name}-thread" if self.mode == "thread"
13
- self.pid_file = Sails.root.join("tmp/#{ThreadDaemon.app_name}.pid")
14
- self.options = options
15
- end
16
-
17
- def read_pid
18
- if !File.exist?(pid_file)
19
- return nil
20
- end
21
-
22
- pid = File.open(pid_file).read.to_i
23
- begin
24
- Process.getpgid(pid)
25
- rescue
26
- pid = nil
27
- end
28
- return pid
29
- end
30
-
31
- def start_process(options = {})
32
- $PROGRAM_NAME = self.app_name
33
- old_pid = read_pid
34
- if old_pid != nil
35
- puts "Current have #{app_name} process in running on pid #{old_pid}"
36
- return
37
- end
38
-
39
- pid = fork do
40
- Sails.start!(self.mode)
41
- end
42
- File.open(pid_file, "w+") do |f|
43
- f.puts pid
44
- end
45
-
46
- puts "Started #{app_name} on pid: #{pid}"
47
-
48
- if options[:daemon] == false
49
- Process.waitpid(pid)
50
- end
51
- end
52
-
53
- def stop_process
54
- pid = read_pid
55
- if pid == nil
56
- puts "#{app_name} process not found, pid #{pid}"
57
- return
58
- end
59
-
60
- print "Stopping #{app_name} with pid: #{pid}..."
61
- begin
62
- Process.kill("QUIT", pid)
63
- ensure
64
- File.delete(pid_file)
65
- end
66
- puts " [Done]"
67
- end
68
- end
69
- end
70
-
71
5
  class CLI < Thor
72
6
  include Thor::Actions
73
7
 
74
8
  map '-v' => :version
9
+ map 's' => :start
10
+ map 'c' => :console
75
11
 
76
12
  def self.source_root
77
13
  __dir__
@@ -83,27 +19,36 @@ module Sails
83
19
  end
84
20
  }
85
21
 
22
+ # sails start
23
+ #
24
+ # Start a thrift app server
86
25
  option :daemon, type: :boolean, default: false
87
26
  option :mode, default: 'nonblocking'
88
27
  desc "start", "Start Thrift server"
89
28
  def start()
90
- ThreadDaemon.init(mode: options[:mode])
91
- ThreadDaemon.start_process(daemon: options[:daemon])
29
+ Sails::Daemon.init(mode: options[:mode])
30
+ Sails::Daemon.start_process(daemon: options[:daemon])
92
31
  end
93
32
 
33
+ # sails stop
34
+ #
35
+ # Stop thrift app server
94
36
  option :mode, default: 'nonblocking'
95
37
  desc "stop", "Stop Thrift server"
96
38
  def stop()
97
- ThreadDaemon.init(mode: options[:mode])
98
- ThreadDaemon.stop_process
39
+ Sails::Daemon.init(mode: options[:mode])
40
+ Sails::Daemon.stop_process
99
41
  end
100
-
42
+
43
+ # sails restart
44
+ #
45
+ # Restart thrift app server
101
46
  option :mode, default: 'nonblocking'
102
47
  desc "restart", "Restart Thrift server"
103
48
  def restart()
104
- ThreadDaemon.init(mode: options[:mode])
105
- ThreadDaemon.stop_process
106
- ThreadDaemon.start_process(daemon: true)
49
+ Sails::Daemon.init(mode: options[:mode])
50
+ Sails::Daemon.stop_process
51
+ Sails::Daemon.start_process(daemon: true)
107
52
  end
108
53
 
109
54
  desc "new APP_NAME", "Create a project"
@@ -125,6 +70,11 @@ module Sails
125
70
  @rel_dir = nil
126
71
  end
127
72
 
73
+ desc "console", "Enter Sails console"
74
+ def console
75
+ Sails::Console.start(Sails.root.join("config/application.rb"))
76
+ end
77
+
128
78
  desc "version", "Show Sails version"
129
79
  def version
130
80
  puts "Sails #{Sails.version}"
@@ -0,0 +1,25 @@
1
+ module Sails
2
+ class Config
3
+ include ActiveSupport::Configurable
4
+
5
+ def initialize
6
+ init_defaults!
7
+ end
8
+
9
+ def init_defaults!
10
+ config.app_name = "Sails"
11
+ config.cache_store = [:memory_store]
12
+ config.autoload_paths = %W(app/models app/models/concerns app/workers app/services app/services/concerns lib)
13
+ config.i18n = I18n
14
+ config.i18n.load_path += Dir[Sails.root.join('config', 'locales', '*.{rb,yml}').to_s]
15
+ config.i18n.default_locale = :en
16
+ config.cache_classes = false
17
+
18
+ config.port = 4000
19
+ config.thread_port = 4001
20
+ config.processor = nil
21
+ config.thread_size = 20
22
+ config.protocol = :binary
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ require "irb"
2
+ require "irb/ext/loader"
3
+
4
+ module Sails
5
+ module ConsoleMethods
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ end
10
+
11
+ def service
12
+ Sails.service
13
+ end
14
+
15
+ def reload!
16
+ puts "Reloading..."
17
+ Sails.reload!(force: true)
18
+ return true
19
+ end
20
+ end
21
+
22
+ class Console
23
+ class << self
24
+ def start(app_path)
25
+ new(app_path).start
26
+ end
27
+ end
28
+
29
+ def initialize(app_path)
30
+ @app_path = app_path
31
+ end
32
+
33
+ def start
34
+ puts "Loading #{Sails.env} environment (Sails #{Sails.version})"
35
+ IRB.conf[:IRB_NAME] = "Sails console"
36
+ require @app_path
37
+ ARGV.clear
38
+ if defined?(IRB::ExtendCommandBundle)
39
+ IRB::ExtendCommandBundle.send :include, Sails::ConsoleMethods
40
+ end
41
+ IRB.start()
42
+ end
43
+ end
44
+ end