shatter-rb 0.0.2 → 0.1.0
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 +4 -4
- data/.husky/commit-msg +5 -0
- data/.rubocop.yml +4 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/Gemfile +0 -2
- data/Gemfile.lock +51 -8
- data/Guardfile +72 -0
- data/README.md +76 -14
- data/commitlint.config.js +1 -0
- data/example_app/Gemfile +3 -2
- data/example_app/Gemfile.lock +9 -16
- data/example_app/app/application.rb +4 -0
- data/example_app/app/functions/hello_world_function.rb +8 -16
- data/example_app/app/service_definition.rb +2 -6
- data/example_app/application.rb +4 -2
- data/example_app/bin/service +2 -2
- data/example_app/config/environment.rb +13 -7
- data/example_app/config.ru +8 -0
- data/exe/console +1 -1
- data/exe/shatter +33 -23
- data/lib/shatter/config.rb +14 -4
- data/lib/shatter/service/base.rb +28 -35
- data/lib/shatter/service/discovery.rb +32 -19
- data/lib/shatter/service/function.rb +45 -31
- data/lib/shatter/service/response_pool.rb +12 -7
- data/lib/shatter/service/service_definition.rb +10 -4
- data/lib/shatter/util.rb +21 -5
- data/lib/shatter/version.rb +1 -1
- data/lib/shatter/web/application.rb +34 -32
- data/lib/shatter/web/server.rb +25 -18
- data/lib/shatter.rb +59 -11
- data/package.json +7 -0
- data/templates/Gemfile.template +1 -3
- data/templates/application.erb +2 -6
- data/templates/config.ru +8 -0
- data/templates/environment.rb.erb +9 -8
- data/templates/function_definition.ts.erb +5 -0
- data/templates/hello_world_function.rb.erb +6 -14
- data/templates/service_client.ts.erb +25 -0
- data/templates/service_definition.rb.erb +3 -7
- data/yarn.lock +1338 -0
- metadata +115 -25
- data/example_app/bin/console +0 -11
- data/lib/shatter/service/function_params.rb +0 -21
- data/shatter.gemspec +0 -51
data/lib/shatter/service/base.rb
CHANGED
@@ -1,71 +1,64 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'benchmark'
|
2
|
+
|
4
3
|
require "drb/drb"
|
5
|
-
require "zk"
|
6
4
|
require "concurrent-ruby"
|
7
5
|
|
8
6
|
# Server Side of the drb
|
9
7
|
module Shatter
|
10
8
|
module Service
|
11
9
|
class Base
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
class ReloadWrapper
|
11
|
+
def self.method_missing(method, *args, &)
|
12
|
+
Shatter::RELOAD_RW_LOCK.with_write_lock do
|
13
|
+
Shatter.reload
|
14
|
+
end
|
15
|
+
Shatter::RELOAD_RW_LOCK.with_read_lock do
|
16
|
+
Shatter::Service::Base.send(method, *args)
|
17
|
+
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
21
|
+
include Concurrent::Async
|
22
|
+
|
22
23
|
class << self
|
23
|
-
|
24
|
-
attr_writer :service_definition
|
24
|
+
attr_accessor :service_definition
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.response_for(uuid)
|
28
|
-
ResponsePool.instance.pool[uuid]
|
28
|
+
Shatter::Service::ResponsePool.instance.pool[uuid]
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.respond_to_missing?(method)
|
32
|
-
@service_definition.
|
32
|
+
@service_definition.new.respond_to?(method)
|
33
33
|
end
|
34
34
|
|
35
35
|
def self.set_static_result_for(uuid, result)
|
36
|
-
|
37
|
-
populate_pool_with_result(Time.now, {uuid:, result:}, nil)
|
36
|
+
populate_pool_with_result(Time.now, { uuid:, result: }, nil)
|
38
37
|
end
|
39
38
|
|
40
39
|
def self.method_missing(method, *args, &)
|
41
|
-
|
40
|
+
super unless respond_to_missing?(method)
|
42
41
|
uuid = args[0].is_a?(Hash) ? args[0][:uuid] : args[0].uuid
|
43
|
-
return {error:
|
42
|
+
return { error: "missing uuid" } if uuid.nil?
|
43
|
+
|
44
44
|
future = @service_definition.new.async.send(method, *args, &)
|
45
45
|
future.add_observer(self, :populate_pool_with_result)
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.populate_pool_with_result(
|
49
|
-
if err
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
key = nil
|
55
|
-
key = Util.zookeeper_response_key(value[:uuid])
|
56
|
-
my_ip = ENV["HOST_NAME"] || "localhost"
|
57
|
-
host = "#{my_ip}:#{Shatter::Config.service_port}"
|
58
|
-
Shatter.logger.info "Recording location of #{value[:uuid]} at #{host} #{value}"
|
59
|
-
zk.create(key, host)
|
60
|
-
my_ip
|
61
|
-
rescue Exception => e
|
48
|
+
def self.populate_pool_with_result(_time, value, err)
|
49
|
+
Shatter.logger.info err if err
|
50
|
+
Shatter.logger.info "#{value[:uuid]} => #{value}" unless err
|
51
|
+
Shatter::Service::ResponsePool.instance.pool[value[:uuid]] = value
|
52
|
+
Shatter::Service::Discovery.populate_result_location(value[:uuid])
|
53
|
+
rescue StandardError => e
|
62
54
|
Shatter.logger.error e
|
63
55
|
raise e
|
64
56
|
end
|
65
57
|
|
66
58
|
def self.close
|
67
59
|
logger = Shatter.logger
|
68
|
-
logger.info "Closing down DRb service"
|
60
|
+
logger.info "Closing down DRb service: #{@service_instance}"
|
61
|
+
@service_instance.stop_service
|
69
62
|
port = Shatter::Config.service_port
|
70
63
|
uri = "localhost:#{port}"
|
71
64
|
logger.info "Removing my existnce at #{port} to zookeeper"
|
@@ -80,7 +73,7 @@ module Shatter
|
|
80
73
|
logger.info "Logging my existnce at #{uri} to zookeeper"
|
81
74
|
Shatter::Service::Discovery.register_service(uri)
|
82
75
|
logger.info "Starting DRb service"
|
83
|
-
DRb.start_service("druby://#{uri}", self)
|
76
|
+
@service_instance = DRb.start_service("druby://#{uri}", Shatter::Config.reload_classes ? ReloadWrapper : self)
|
84
77
|
logger.info "DRb service started"
|
85
78
|
DRb.thread.join
|
86
79
|
end
|
@@ -90,4 +83,4 @@ module Shatter
|
|
90
83
|
end
|
91
84
|
end
|
92
85
|
end
|
93
|
-
end
|
86
|
+
end
|
@@ -1,25 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zk"
|
1
4
|
module Shatter
|
2
5
|
module Service
|
3
6
|
class Discovery
|
4
7
|
class << self
|
8
|
+
def connection_pool
|
9
|
+
@connection_pool ||= ZK::Pool::Bounded.new(Shatter::Config.zookeeper_host)
|
10
|
+
end
|
5
11
|
|
6
12
|
def deregister_service(service_url)
|
7
|
-
zk =
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
zk.close
|
13
|
+
zk = connection_pool.checkout
|
14
|
+
key = Shatter::Util.instances_key
|
15
|
+
zk.delete("#{key}/#{service_url}") if zk.exists?("#{key}/#{service_url}")
|
16
|
+
connection_pool.checkin(zk)
|
12
17
|
end
|
13
18
|
|
14
19
|
def register_service(service_url)
|
15
20
|
Shatter.logger.info "Registering #{service_url} to zookeeper"
|
16
|
-
zk =
|
17
|
-
|
18
|
-
|
21
|
+
zk = connection_pool.checkout
|
22
|
+
key = Shatter::Util.instances_key
|
23
|
+
unless zk.exists?("#{key}/#{service_url}")
|
24
|
+
created = zk.create("#{key}/#{service_url}")
|
19
25
|
Shatter.logger.info "Registered #{created}"
|
20
26
|
end
|
21
|
-
|
22
|
-
zk.close
|
27
|
+
connection_pool.checkin(zk)
|
23
28
|
end
|
24
29
|
|
25
30
|
def service_instance_url
|
@@ -27,23 +32,31 @@ module Shatter
|
|
27
32
|
end
|
28
33
|
|
29
34
|
def service_instance_urls
|
30
|
-
zk =
|
31
|
-
urls = zk.children(
|
32
|
-
zk
|
35
|
+
zk = connection_pool.checkout
|
36
|
+
urls = zk.children(Shatter::Util.instances_key)
|
37
|
+
connection_pool.checkin(zk)
|
33
38
|
urls
|
34
39
|
end
|
35
40
|
|
41
|
+
def populate_result_location(uuid)
|
42
|
+
zk = connection_pool.checkout
|
43
|
+
zk.create(Util.zookeeper_response_key(uuid), my_host)
|
44
|
+
connection_pool.checkin(zk)
|
45
|
+
end
|
46
|
+
|
47
|
+
def my_host
|
48
|
+
my_ip = ENV["HOST_NAME"] || "localhost"
|
49
|
+
"#{my_ip}:#{Shatter::Config.service_port}"
|
50
|
+
end
|
51
|
+
|
36
52
|
def service_instance_url_for_uuid(uuid)
|
37
|
-
druby_instance_url = nil
|
38
53
|
key = Util.zookeeper_response_key(uuid)
|
39
|
-
zk =
|
54
|
+
zk = connection_pool.checkout
|
40
55
|
druby_instance_url = zk.get(key)[0] if zk.exists?(key)
|
41
|
-
zk
|
42
|
-
Shatter.logger.debug "Service instance url for #{uuid} - #{druby_instance_url}"
|
43
|
-
|
56
|
+
connection_pool.checkin(zk)
|
44
57
|
druby_instance_url
|
45
58
|
end
|
46
59
|
end
|
47
60
|
end
|
48
61
|
end
|
49
|
-
end
|
62
|
+
end
|
@@ -1,56 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
|
1
5
|
module Shatter
|
2
6
|
module Service
|
3
7
|
class Function
|
4
|
-
|
5
8
|
def self.define_param(name, type:, nullable: true)
|
6
|
-
|
7
|
-
|
9
|
+
@param_meta ||= {}
|
10
|
+
@param_meta[name] = { name:, type:, nullable: }
|
8
11
|
end
|
9
12
|
|
10
13
|
def self.meta
|
11
|
-
|
14
|
+
@param_meta || {}
|
12
15
|
end
|
16
|
+
define_param :uuid, nullable: false, type: "string"
|
13
17
|
|
14
|
-
|
18
|
+
attr_reader :params
|
15
19
|
|
16
20
|
def initialize(function_params)
|
17
21
|
@params = function_params
|
18
22
|
end
|
19
23
|
|
20
|
-
def params
|
21
|
-
Hash[@@param_meta.keys.map { |k| [k]}].merge(@params)
|
22
|
-
end
|
23
|
-
|
24
24
|
def call
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
{ result: nil, error: "Invalid Parameters" } unless valid_params?
|
26
|
+
{ result: nil, error: nil }.merge(invoke.merge(uuid: params[:uuid]))
|
27
|
+
rescue StandardError => e
|
28
|
+
Shatter.logger.error e.message
|
29
|
+
Shatter.logger.error e.backtrace
|
30
|
+
{ result: nil, error: "Something Went Wrong", uuid: params[:uuid] }
|
30
31
|
end
|
31
32
|
|
32
33
|
def valid_params?
|
33
|
-
self.class.meta.
|
34
|
-
|
35
|
-
val = @params[arg]
|
36
|
-
puts meta
|
37
|
-
raise "#{arg} cannot be nil" if !meta[:nullable] && val.nil?
|
38
|
-
raise "expected #{arg} to be a string" if meta[:type] == 'string' && !val.is_a?(String)
|
39
|
-
|
40
|
-
if meta[:type] == 'integer'
|
41
|
-
if !meta[:nullable] && val.nil?
|
42
|
-
raise 'value cannot be nil'
|
43
|
-
end
|
44
|
-
if !val.nil? && !val.is_a?(Integer)
|
45
|
-
raise "expected #{arg} to be an integer"
|
46
|
-
end
|
47
|
-
end
|
34
|
+
self.class.meta.each_key do |arg|
|
35
|
+
return false unless valid_param?(arg)
|
48
36
|
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def valid_param?(arg)
|
41
|
+
meta = self.class.meta[arg]
|
42
|
+
return false if meta.nil?
|
43
|
+
|
44
|
+
meta => type:, nullable:
|
45
|
+
val = value_for_arg(arg)
|
46
|
+
return nullable if val.nil?
|
47
|
+
|
48
|
+
return false if type == "string" && !val.is_a?(String)
|
49
|
+
return false if type == "integer" && !val.is_a?(Integer)
|
50
|
+
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def value_for_arg(arg)
|
55
|
+
@params[arg.to_s] || @params[arg.to_sym]
|
49
56
|
end
|
50
57
|
|
51
58
|
def self.invoke
|
52
|
-
raise
|
59
|
+
raise "cant invoke for base function"
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.to_typescript
|
63
|
+
function_nm = Shatter::Service::Base.service_definition.function_collection.to_a.detect do |fn_def|
|
64
|
+
fn_def[1] == self
|
65
|
+
end[0]
|
66
|
+
ERB.new(File.read("#{__dir__}/../../../templates/function_definition.ts.erb")).result(binding)
|
53
67
|
end
|
54
68
|
end
|
55
69
|
end
|
56
|
-
end
|
70
|
+
end
|
@@ -1,10 +1,15 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "singleton"
|
2
4
|
module Shatter
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module Service
|
6
|
+
class ResponsePool
|
7
|
+
include Singleton
|
8
|
+
attr_reader :pool
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@pool = {}
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
|
-
end
|
15
|
+
end
|
@@ -1,15 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "concurrent-ruby"
|
2
|
-
require 'set'
|
3
4
|
|
4
5
|
module Shatter
|
5
6
|
module Service
|
6
7
|
class ServiceDefinition
|
7
8
|
include Concurrent::Async
|
8
9
|
class << self
|
9
|
-
|
10
|
+
attr_accessor :function_collection
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_typescript
|
14
|
+
function_defs = @function_collection.values
|
15
|
+
ERB.new(File.read("#{__dir__}/../../../templates/service_client.ts.erb")).result(binding)
|
10
16
|
end
|
17
|
+
|
11
18
|
def self.register_function(identifier, function)
|
12
|
-
Shatter.logger.info "Registering function - #{identifier} for #{self}"
|
13
19
|
@function_collection ||= {}
|
14
20
|
@function_collection[identifier.to_s] = function
|
15
21
|
define_method identifier do |params|
|
@@ -18,4 +24,4 @@ module Shatter
|
|
18
24
|
end
|
19
25
|
end
|
20
26
|
end
|
21
|
-
end
|
27
|
+
end
|
data/lib/shatter/util.rb
CHANGED
@@ -1,19 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "singleton"
|
5
|
+
|
6
|
+
class String
|
7
|
+
def camel_case_lower
|
8
|
+
split("_").inject([]) { |buffer, e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
|
9
|
+
end
|
10
|
+
end
|
4
11
|
|
5
12
|
module Shatter
|
6
13
|
module Util
|
7
14
|
class Logger < ::Logger
|
8
15
|
include Singleton
|
9
16
|
def initialize
|
10
|
-
super(
|
17
|
+
super($stdout, datetime_format: "%Y-%m-%d %H:%M:%S")
|
11
18
|
end
|
12
19
|
end
|
13
20
|
|
21
|
+
def self.instances_key
|
22
|
+
"/shater_service_instances"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.zookeeper_response_key_root
|
26
|
+
"/shatter::response_data_locations"
|
27
|
+
end
|
28
|
+
|
14
29
|
def self.zookeeper_response_key(uuid)
|
15
|
-
raise
|
16
|
-
|
30
|
+
raise "Cant produce key without uuid" if uuid.nil?
|
31
|
+
|
32
|
+
"#{zookeeper_response_key_root}/#{uuid}"
|
17
33
|
end
|
18
34
|
end
|
19
35
|
end
|
data/lib/shatter/version.rb
CHANGED
@@ -3,48 +3,50 @@
|
|
3
3
|
require "drb/drb"
|
4
4
|
require "concurrent-ruby"
|
5
5
|
|
6
|
-
require_relative "./application"
|
7
|
-
|
8
6
|
module Shatter
|
9
7
|
module Web
|
10
8
|
class Application
|
11
9
|
include Concurrent::Async
|
12
10
|
|
13
11
|
def response_for(uuid)
|
14
|
-
|
15
|
-
return
|
16
|
-
|
12
|
+
client = service_client(Shatter::Service::Discovery.service_instance_url_for_uuid(uuid))
|
13
|
+
return if client.nil?
|
14
|
+
|
15
|
+
client.response_for(uuid)
|
17
16
|
end
|
18
17
|
|
19
18
|
def route(uuid, path, params)
|
20
|
-
operation = path
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
.send(
|
34
|
-
operation.to_sym,
|
35
|
-
func_params
|
36
|
-
)
|
37
|
-
rescue ArgumentError => e
|
38
|
-
DRbObject.new_with_uri("druby://#{Shatter::Service::Discovery.service_instance_url}")
|
39
|
-
.set_static_result_for(uuid, {result: nil, error: e.message })
|
40
|
-
end
|
41
|
-
end
|
42
|
-
rescue Exception => e
|
43
|
-
Shatter.logger.error "caught error: #{e.message}"
|
44
|
-
Shatter.logger.error "#{e.backtrace.join("\n")}"
|
45
|
-
{ data:, error: e.message, uuid: }
|
19
|
+
operation = operation_for(path)
|
20
|
+
return unknown_operation(uuid) if operation.nil?
|
21
|
+
|
22
|
+
client = service_client
|
23
|
+
client.send(operation.to_sym, params.merge(uuid:))
|
24
|
+
rescue StandardError => e
|
25
|
+
error_response(uuid, e)
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def unknown_operation(uuid)
|
31
|
+
service_client.set_static_result_for(uuid, { result: nil, error: :unknown_operation })
|
46
32
|
end
|
47
33
|
|
34
|
+
def error_response(uuid, err)
|
35
|
+
Shatter.logger.error err
|
36
|
+
service_client.set_static_result_for(uuid, { result: nil, error: "Something went wrong" })
|
37
|
+
end
|
38
|
+
|
39
|
+
def service_client(druby_instance_url = Shatter::Service::Discovery.service_instance_url)
|
40
|
+
return if druby_instance_url.nil?
|
41
|
+
|
42
|
+
DRbObject.new_with_uri("druby://#{druby_instance_url}")
|
43
|
+
end
|
44
|
+
|
45
|
+
def operation_for(path)
|
46
|
+
operation = path.scan(%r{/(.+)$}).first&.first
|
47
|
+
function = Shatter::Service::Base.service_definition.function_collection[operation]
|
48
|
+
function.nil? ? nil : operation
|
49
|
+
end
|
48
50
|
end
|
49
51
|
end
|
50
|
-
end
|
52
|
+
end
|
data/lib/shatter/web/server.rb
CHANGED
@@ -6,40 +6,47 @@ require "json"
|
|
6
6
|
module Shatter
|
7
7
|
module Web
|
8
8
|
class Server
|
9
|
-
|
10
9
|
class << self
|
11
|
-
|
12
|
-
attr_writer :application
|
10
|
+
attr_accessor :application
|
13
11
|
end
|
14
12
|
|
15
13
|
def self.call(env)
|
16
14
|
request = Rack::Request.new(env)
|
17
|
-
path = env["PATH_INFO"]
|
18
15
|
if env["PATH_INFO"] == "/callbacks"
|
19
|
-
uuid = env[
|
20
|
-
|
21
|
-
elsif
|
22
|
-
|
16
|
+
uuid = env["QUERY_STRING"].split("=")[1]
|
17
|
+
handle_response_for_request(uuid)
|
18
|
+
elsif request.post?
|
19
|
+
handle_operation_request(env)
|
23
20
|
else
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
[404, {}, []]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.handle_operation_request(env)
|
26
|
+
request = Rack::Request.new(env)
|
27
|
+
params = begin
|
28
|
+
JSON.parse(request.body.read, { symbolize_names: true })
|
29
|
+
rescue StandardError
|
30
|
+
{}
|
29
31
|
end
|
32
|
+
uuid = SecureRandom.uuid
|
33
|
+
future = application.new.async.route(uuid, request.path, params)
|
34
|
+
future.add_observer(:service_callback, self)
|
35
|
+
[200, { "delay" => Shatter::Config.initial_delay, "location" => "/callbacks?uuid=#{uuid}" }, []]
|
30
36
|
end
|
31
37
|
|
32
|
-
def self.
|
38
|
+
def self.service_callback(_time, _value, error)
|
33
39
|
return if error.nil?
|
34
|
-
|
40
|
+
|
41
|
+
Shatter.logger.error error.to_s
|
35
42
|
end
|
36
43
|
|
37
|
-
def self.
|
44
|
+
def self.handle_response_for_request(uuid)
|
38
45
|
response = application.new.response_for(uuid)
|
39
46
|
return [200, {}, [response.to_json]] unless response.nil?
|
40
47
|
|
41
|
-
[200, { "delay" =>
|
48
|
+
[200, { "delay" => Shatter::Config.missing_result_delay, "location" => "/callbacks?uuid=#{uuid}" }, []]
|
42
49
|
end
|
43
50
|
end
|
44
51
|
end
|
45
|
-
end
|
52
|
+
end
|
data/lib/shatter.rb
CHANGED
@@ -1,21 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require_relative "shatter/
|
9
|
-
require_relative "shatter/
|
10
|
-
require_relative "shatter/
|
11
|
-
require_relative "shatter/util"
|
12
|
-
|
13
|
-
$stdout.sync = true
|
3
|
+
require "zeitwerk"
|
4
|
+
require "concurrent/atomic/read_write_lock"
|
5
|
+
Dir["#{__dir__}/shatter/service/*.rb"].each { |file| require file }
|
6
|
+
Dir["#{__dir__}/shatter/web/*.rb"].each { |file| require file }
|
7
|
+
Dir["#{__dir__}/shatter/ext/*.rb"].each { |file| require file }
|
8
|
+
require_relative "./shatter/config"
|
9
|
+
require_relative "./shatter/util"
|
10
|
+
require_relative "./shatter/version"
|
14
11
|
|
15
12
|
module Shatter
|
16
13
|
class Error < StandardError; end
|
14
|
+
|
15
|
+
def self.root
|
16
|
+
current = Dir.pwd
|
17
|
+
root_dir = nil
|
18
|
+
|
19
|
+
while current.size >= 1 && root_dir.nil?
|
20
|
+
root_dir = current if Dir.children(current).include?("Gemfile")
|
21
|
+
current = File.expand_path("..", current) if root_dir.nil?
|
22
|
+
Dir.new(current)
|
23
|
+
end
|
24
|
+
root_dir
|
25
|
+
end
|
26
|
+
|
17
27
|
def self.logger
|
18
28
|
Util::Logger.instance
|
19
29
|
end
|
30
|
+
|
31
|
+
def self.config(&block)
|
32
|
+
block.call(Config) and return if block_given?
|
33
|
+
|
34
|
+
Config
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.loader
|
38
|
+
@loader
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.load_environment
|
42
|
+
require "#{Shatter.root}/config/environment.rb"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.reload
|
46
|
+
@loader.reload
|
47
|
+
link_definitions
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.load
|
51
|
+
# @loader = Zeitwerk::Loader.for_gem
|
52
|
+
@loader = Zeitwerk::Loader.new
|
53
|
+
@loader.tag = File.basename(__FILE__, ".rb")
|
54
|
+
@loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
|
55
|
+
Config.autoload_paths.each do |path|
|
56
|
+
@loader.push_dir(File.expand_path(path, root))
|
57
|
+
end
|
58
|
+
@loader.enable_reloading
|
59
|
+
@loader.setup # ready!
|
60
|
+
link_definitions
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.link_definitions
|
64
|
+
Shatter::Service::Base.service_definition = ServiceDefinition if Object.const_defined?("ServiceDefinition")
|
65
|
+
Shatter::Web::Server.application = Application if Object.const_defined?("Application")
|
66
|
+
end
|
20
67
|
# Your code goes here...
|
21
68
|
end
|
69
|
+
Shatter::RELOAD_RW_LOCK = Concurrent::ReadWriteLock.new
|
data/package.json
ADDED
data/templates/Gemfile.template
CHANGED
data/templates/application.erb
CHANGED
data/templates/config.ru
CHANGED
@@ -2,8 +2,16 @@
|
|
2
2
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "shatter"
|
5
|
+
require "rack/cors"
|
5
6
|
|
6
7
|
require_relative "./config/environment"
|
7
8
|
|
8
9
|
use Rack::CommonLogger
|
10
|
+
|
11
|
+
use Rack::Cors do
|
12
|
+
allow do
|
13
|
+
origins "*"
|
14
|
+
resource "*", headers: :any, methods: %i[get post patch put], expose: %w[delay location]
|
15
|
+
end
|
16
|
+
end
|
9
17
|
run Shatter::Web::Server
|