shatter-rb 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.husky/commit-msg +5 -0
  3. data/.rubocop.yml +4 -0
  4. data/.ruby-version +1 -1
  5. data/.tool-versions +1 -1
  6. data/Gemfile +0 -2
  7. data/Gemfile.lock +51 -8
  8. data/Guardfile +72 -0
  9. data/README.md +76 -14
  10. data/commitlint.config.js +1 -0
  11. data/example_app/Gemfile +3 -2
  12. data/example_app/Gemfile.lock +9 -16
  13. data/example_app/app/application.rb +4 -0
  14. data/example_app/app/functions/hello_world_function.rb +8 -16
  15. data/example_app/app/service_definition.rb +2 -6
  16. data/example_app/application.rb +4 -2
  17. data/example_app/bin/service +2 -2
  18. data/example_app/config/environment.rb +13 -7
  19. data/example_app/config.ru +8 -0
  20. data/exe/console +1 -1
  21. data/exe/shatter +33 -23
  22. data/lib/shatter/config.rb +14 -4
  23. data/lib/shatter/service/base.rb +28 -35
  24. data/lib/shatter/service/discovery.rb +32 -19
  25. data/lib/shatter/service/function.rb +45 -31
  26. data/lib/shatter/service/response_pool.rb +12 -7
  27. data/lib/shatter/service/service_definition.rb +10 -4
  28. data/lib/shatter/util.rb +21 -5
  29. data/lib/shatter/version.rb +1 -1
  30. data/lib/shatter/web/application.rb +34 -32
  31. data/lib/shatter/web/server.rb +25 -18
  32. data/lib/shatter.rb +59 -11
  33. data/package.json +7 -0
  34. data/templates/Gemfile.template +1 -3
  35. data/templates/application.erb +2 -6
  36. data/templates/config.ru +8 -0
  37. data/templates/environment.rb.erb +9 -8
  38. data/templates/function_definition.ts.erb +5 -0
  39. data/templates/hello_world_function.rb.erb +6 -14
  40. data/templates/service_client.ts.erb +25 -0
  41. data/templates/service_definition.rb.erb +3 -7
  42. data/yarn.lock +1338 -0
  43. metadata +115 -25
  44. data/example_app/bin/console +0 -11
  45. data/lib/shatter/service/function_params.rb +0 -21
  46. data/shatter.gemspec +0 -51
@@ -1,71 +1,64 @@
1
1
  # frozen_string_literal: true
2
- require 'singleton'
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
- include Concurrent::Async
13
-
14
- class ZooKeeperConnection
15
- include Singleton
16
- attr_reader :client
17
- def initialize
18
- @client = ZK.new(Shatter::Config.zookeeper_host)
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
- attr_reader :service_definition
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.instance_methods.include?(method.to_sym)
32
+ @service_definition.new.respond_to?(method)
33
33
  end
34
34
 
35
35
  def self.set_static_result_for(uuid, result)
36
- puts "Setting static content"
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
- Shatter.logger.info "Mapping #{method}"
40
+ super unless respond_to_missing?(method)
42
41
  uuid = args[0].is_a?(Hash) ? args[0][:uuid] : args[0].uuid
43
- return {error: 'missing uuid'} if uuid.nil?
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(time, value, err)
49
- if err
50
- Shatter.logger.info err
51
- end
52
- ResponsePool.instance.pool[value[:uuid]] = value
53
- zk = ZooKeeperConnection.instance.client
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 = ZK.new (Shatter::Config.zookeeper_host)
8
- if zk.exists?("/shater_service_instances/#{service_url}")
9
- zk.delete("/shater_service_instances/#{service_url}")
10
- end
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 = ZK.new (Shatter::Config.zookeeper_host)
17
- unless zk.exists?("/shater_service_instances/#{service_url}")
18
- created = zk.create("/shater_service_instances/#{service_url}")
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
- puts zk.children("/shater_service_instances")
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 = ZK.new (Shatter::Config.zookeeper_host)
31
- urls = zk.children("/shater_service_instances")
32
- zk.close
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 = ZK.new(Shatter::Config.zookeeper_host)
54
+ zk = connection_pool.checkout
40
55
  druby_instance_url = zk.get(key)[0] if zk.exists?(key)
41
- zk.close
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
- @@param_meta ||= {}
7
- @@param_meta[name] = {name:, type:, nullable:}
9
+ @param_meta ||= {}
10
+ @param_meta[name] = { name:, type:, nullable: }
8
11
  end
9
12
 
10
13
  def self.meta
11
- @@param_meta
14
+ @param_meta || {}
12
15
  end
16
+ define_param :uuid, nullable: false, type: "string"
13
17
 
14
- define_param :uuid, nullable: false, type: 'string'
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
- raise 'Invalid Args' unless valid_params?
26
- valid_keys = @@param_meta.keys
27
- {result: nil, error:nil}.merge(self.invoke.merge(uuid: params[:uuid]))
28
- rescue Exception => e
29
- {result: nil, error: e.message, uuid: params[:uuid]}
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.keys.each do |arg|
34
- meta = self.class.meta[arg]
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 'cant invoke for base function'
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
- require 'singleton'
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
2
4
  module Shatter
3
- class ResponsePool
4
- include Singleton
5
- attr_reader :pool
6
- def initialize
7
- @pool = {}
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
- attr_reader :function_collection
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
- require 'logger'
3
- require 'singleton'
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(STDOUT, datetime_format: '%Y-%m-%d %H:%M:%S')
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 'Cant produce key without uuid' if uuid.nil?
16
- "/shatter::response_data_locations/#{uuid}"
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shatter
4
- VERSION = "0.0.2"
4
+ VERSION = "0.1.0"
5
5
  end
@@ -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
- druby_instance_url = Shatter::Service::Discovery.service_instance_url_for_uuid(uuid)
15
- return unless druby_instance_url
16
- DRbObject.new_with_uri("druby://#{druby_instance_url}").response_for(uuid)
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.scan(/\/(.+)$/).first&.first
21
- raise 'failed to route' if operation.nil?
22
- Shatter.logger.info Shatter::Service::Base.service_definition.function_collection
23
- Shatter.logger.info operation
24
- function = Shatter::Service::Base.service_definition.function_collection[operation]
25
- if function.nil?
26
- DRbObject.new_with_uri("druby://#{Shatter::Service::Discovery.service_instance_url}")
27
- .set_static_result_for(uuid, {result: nil, error: :unknown_operation})
28
- else
29
- begin
30
- func_params = params.merge(uuid:)
31
- Shatter.logger.info "routing #{path}/#{func_params}"
32
- DRbObject.new_with_uri("druby://#{Shatter::Service::Discovery.service_instance_url}")
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
@@ -6,40 +6,47 @@ require "json"
6
6
  module Shatter
7
7
  module Web
8
8
  class Server
9
-
10
9
  class << self
11
- attr_reader :application
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['QUERY_STRING'].split("=")[1]
20
- response_for(uuid)
21
- elsif env["PATH_INFO"] == "/base_time"
22
- [200, {}, [""]]
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
- params = JSON.parse(request.body.read, {symbolize_names: true})
25
- uuid = SecureRandom.uuid
26
- future = application.new.async.route(uuid, path, params)
27
- future.add_observer(:server_call_result, self)
28
- [200, { "delay" => "20", "location" => "/callbacks?uuid=#{uuid}" }, []]
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.server_call_result(time, value, error)
38
+ def self.service_callback(_time, _value, error)
33
39
  return if error.nil?
34
- Shatter.logger.error "#{ error }"
40
+
41
+ Shatter.logger.error error.to_s
35
42
  end
36
43
 
37
- def self.response_for(uuid)
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" => "100", "location" => "/callbacks?uuid=#{uuid}" }, []]
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
- require_relative "shatter/version"
4
- require_relative "shatter/web/application"
5
- require_relative "shatter/config"
6
- require_relative "shatter/web/server"
7
- require_relative "shatter/service/base"
8
- require_relative "shatter/service/discovery"
9
- require_relative "shatter/service/service_definition"
10
- require_relative "shatter/service/response_pool"
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
@@ -0,0 +1,7 @@
1
+ {
2
+ "devDependencies": {
3
+ "@commitlint/cli": "^17.4.2",
4
+ "@commitlint/config-conventional": "^17.4.2",
5
+ "husky": "^8.0.3"
6
+ }
7
+ }
@@ -1,5 +1,3 @@
1
1
  source "https://rubygems.org"
2
- gem 'shatter', path: '..'
3
- gem "zookeeper", "~>1.5.4", github: 'EricRoos/zookeeper'
2
+ gem 'shatter-rb'
4
3
 
5
- gem "foreman", "~> 0.87.2"
@@ -1,6 +1,2 @@
1
- module <%= app_name %>
2
- class Application < Shatter::Web::Application
3
- end
4
- end
5
-
6
- require_relative './app/service_definition'
1
+ class Application < Shatter::Web::Application
2
+ end
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