sc4ry 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ad841dbab3af84cbf8d7153d083add74200824d502a73aacc6d452f8e42a58d8
4
+ data.tar.gz: 7a6fdee9c2e076ba750adcd421bbf1d2115acd9db7778b75e6ffe475234d4db3
5
+ SHA512:
6
+ metadata.gz: dc1df50beebe4fb869ee88118c0cd922c45a02a79bf64b3f5dd9f539942980e0003b1444a1928f6ef0fced339a7672f8b6a65de463cec7ae87976a0c6f7e074e
7
+ data.tar.gz: 3b0d6aed86e5196a7ac829c6efe692d621a410933f2b0213ba37b6fc56748b405e036195cd91375ba581b71a6bfe24d7386fc8335ba600ebc0e0913f2db86f9b
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in sc4ry.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
8
+ gem "prometheus-client", "~> 3.0"
9
+ gem "rest-client", "~> 2.1"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Romain GEORGES
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Sc4ry : Simple CircuitBreacker For RubY
2
+
3
+ Sc4ry provide the Circuit Breaker Design Pattern for your applications
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'sc4ry'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sc4ry
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Development
26
+
27
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+
31
+ ## Contributing
32
+
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sc4ry. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/sc4ry/blob/master/CODE_OF_CONDUCT.md).
34
+
35
+
36
+ ## License
37
+
38
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
39
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "sc4ry"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + '/*.rb'].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -0,0 +1,35 @@
1
+ module Sc4ry
2
+ module Backends
3
+
4
+ class Memory
5
+ def initialize(config=nil?)
6
+ @data = Hash::new
7
+ end
8
+
9
+ def list
10
+ return @data.keys
11
+ end
12
+
13
+ def get(options)
14
+ return @data[options[:key]]
15
+ end
16
+
17
+ def put(options)
18
+ @data[options[:key]] = options[:value]
19
+ end
20
+
21
+ def del(options)
22
+ @data.delete options[:key]
23
+ end
24
+
25
+ def flush
26
+ @data.clear
27
+ end
28
+
29
+ def exist?(options)
30
+ return @data.include? options[:key]
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,65 @@
1
+ module Sc4ry
2
+ module Backends
3
+ # Redis backend definition
4
+ class Redis
5
+
6
+ # Constructor
7
+ # @param [Hash] config Config map
8
+ # @return [Sc4ry::Backends::Redis] a Redis backend
9
+ def initialize(config)
10
+ @auth = config.slice(:auth)[:auth]
11
+ @config = config.slice(:host, :port, :db)
12
+ @be = ::Redis.new @config
13
+ @be.auth(@auth) if @auth
14
+ end
15
+
16
+ # return the list of find records in backend for a specific pattern
17
+ # @return [Array] list of record (for all hostname if hostname is specified)
18
+ def list
19
+ return @store.keys('*')
20
+ end
21
+
22
+
23
+ # return value of queried record
24
+ # @param [Hash] options
25
+ # @option options [Symbol] :key the name of the record
26
+ # @return [String] content value of record
27
+ def get(options)
28
+ return @store.get(options[:key])
29
+ end
30
+
31
+ # defined and store value for specified key
32
+ # @param [Hash] options
33
+ # @option options [Symbol] :key the name of the record
34
+ # @option options [Symbol] :value the content value of the record
35
+ # @return [String] content value of record
36
+ def put(options)
37
+ @store.set options[:key], options[:value]
38
+ end
39
+
40
+ # delete a specific record
41
+ # @param [Hash] options
42
+ # @option options [Symbol] :key the name of the record
43
+ # @return [Boolean] status of the operation
44
+ def del(options)
45
+ @store.del options[:key]
46
+ end
47
+
48
+ # flush all records in backend
49
+ def flush
50
+ @store.flushdb
51
+ end
52
+
53
+ # verifiy a specific record existance
54
+ # @param [Hash] options
55
+ # @option options [Symbol] :key the name of the record
56
+ # @return [Boolean] presence of the record
57
+ def exist?(options)
58
+ return ( not @store.get(options[:key]).nil?)
59
+ end
60
+
61
+
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,93 @@
1
+ module Sc4ry
2
+ class Circuits
3
+
4
+ @@circuits_store = Sc4ry::Store.instance
5
+
6
+ @@config = { :max_failure_count => 5,
7
+ :timeout_value => 20,
8
+ :timeout => false,
9
+ :max_timeout_count => 5,
10
+ :max_time => 10,
11
+ :max_overtime_count => 3,
12
+ :check_delay => 30,
13
+ :notifiers => [],
14
+ :exceptions => [StandardError, RuntimeError]
15
+ }
16
+
17
+ def Circuits.default_config
18
+ return @@config
19
+ end
20
+
21
+ def Circuits.register(options = {})
22
+ raise ":circuit is mandatory" unless options[:circuit]
23
+ name = options[:circuit]
24
+ override = (options[:config].class == Hash)? options[:config] : {}
25
+ config = @@config.merge override
26
+ @@circuits_store.put key: name, value: config
27
+ end
28
+
29
+ def Circuits.list
30
+ return @@circuits_store.list
31
+ end
32
+
33
+
34
+ def Circuits.get(options)
35
+ @@circuits_store.get key: options[:circuit]
36
+ end
37
+
38
+ def Circuits.run(options = {}, &block)
39
+ circuits_list = Circuits.list
40
+ raise "No circuit block given" unless block_given?
41
+ raise "No circuits defined" if circuits_list.empty?
42
+ circuit_name = (options[:circuit])? options[:circuit] : circuits_list.first
43
+ raise "Circuit #{circuit_name} not found" unless circuits_list.include? circuit_name
44
+ circuit = Circuits.get circuit: circuit_name
45
+ skip = false
46
+ if circuit.include? :status then
47
+ if circuit[:status][:general] == :open then
48
+ @now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
49
+ skip = true if ((@now - circuit[:values].last[:end_time]) < circuit[:check_delay])
50
+ end
51
+ end
52
+ unless skip
53
+ controller = Sc4ry::RunController.new(circuit)
54
+ Circuits.control circuit: circuit_name, values: controller.run(block: block)
55
+ end
56
+ Sc4ry::Helpers.log level: :info, message: "Circuit #{circuit_name} : status #{circuit[:status]}"
57
+
58
+ end
59
+
60
+ private
61
+ def Circuits.control(options={})
62
+ data = @@circuits_store.get key: options[:circuit]
63
+ data[:status] = {:general => :closed, :failure_count => 0, :overtime_count => 0, :timeout_count => 0} unless data.include? :status
64
+ data[:values] = Array::new unless data.include? :values
65
+ level = [data[:max_failure_count].to_i, data[:max_timeout_count].to_i, data[:max_overtime_count].to_i].max
66
+ data[:values].shift if data[:values].size > level
67
+ data[:values].push options[:values]
68
+ worst_status = []
69
+ ['failure','overtime','timeout'].each do |control|
70
+ if options[:values][control.to_sym] == true then
71
+ data[:status]["#{control}_count".to_sym] += 1
72
+ else
73
+ data[:status]["#{control}_count".to_sym] = 0
74
+ end
75
+
76
+ case data[:status]["#{control}_count".to_sym]
77
+ when 0
78
+ worst_status.push :closed
79
+ when 1..data["max_#{control}_count".to_sym]
80
+ worst_status.push :half_open
81
+ else
82
+ worst_status.push :open
83
+ end
84
+ end
85
+ save = data[:status][:general]
86
+ [:closed,:half_open,:open].each do |status|
87
+ data[:status][:general] = status if worst_status.include? status
88
+ end
89
+ Sc4ry::Helpers.notify circuit: options[:circuit], config: data if save != data[:status][:general]
90
+ @@circuits_store.put key: options[:circuit], value: data
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,23 @@
1
+ require 'rest-client'
2
+ require 'prometheus/client'
3
+ require 'prometheus/client/push'
4
+
5
+ require 'logger'
6
+ require 'timeout'
7
+ require 'forwardable'
8
+ require 'singleton'
9
+ require 'socket'
10
+ require 'openssl'
11
+ require 'net/http'
12
+ require 'uri'
13
+ require 'json'
14
+
15
+
16
+ require_relative 'helpers'
17
+ require_relative 'logger'
18
+ require_relative 'backends/init'
19
+ require_relative 'store'
20
+ require_relative 'run_controller'
21
+ require_relative 'circuits'
22
+ require_relative 'notifiers/init'
23
+ require_relative 'exporters/init'
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + '/*.rb'].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
@@ -0,0 +1,49 @@
1
+
2
+ module Sc4ry
3
+ module Helpers
4
+
5
+ def Helpers.log(options)
6
+ Sc4ry::Logger.current = options[:target] if options[:target]
7
+ Sc4ry::Logger.get.send options[:level], "Sc4ry : #{options[:message]}"
8
+ end
9
+
10
+ # TCP/IP service checker
11
+ # @return [Bool] status
12
+ # @param [Hash] options
13
+ # @option options [String] :host hostname
14
+ # @option options [String] :port TCP port
15
+ # @option options [String] :url full URL, priority on :host and :port
16
+ def Helpers.verify_service(options ={})
17
+ begin
18
+ if options[:url] then
19
+ uri = URI.parse(options[:url])
20
+ host = uri.host
21
+ port = uri.port
22
+ else
23
+ host = options[:host]
24
+ port = options[:port]
25
+ end
26
+ Timeout::timeout(1) do
27
+ begin
28
+ s = TCPSocket.new(host, port)
29
+ s.close
30
+ return true
31
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
32
+ return false
33
+ end
34
+ end
35
+ rescue Timeout::Error
36
+ return false
37
+ end
38
+ end
39
+
40
+
41
+ def Helpers.notify(options = {})
42
+ Sc4ry::Notifiers.list.each do |record|
43
+ notifier = Sc4ry::Notifiers.get name: record
44
+ notifier[:class].notify(options) if options[:config][:notifiers].include? record
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+
2
+ module Sc4ry
3
+ class Logger
4
+
5
+ @@loggers = {:stdout => ::Logger.new(STDOUT)}
6
+ @@current = :stdout
7
+
8
+ def Logger.list_avaible
9
+ return @@loggers
10
+ end
11
+
12
+ def Logger.current
13
+ return @@current
14
+ end
15
+
16
+ def Logger.get
17
+ return @@loggers[@@current]
18
+ end
19
+
20
+ def Logger.current=(sym)
21
+ raise "Logger not define : #{sim}" unless @@loggers.keys.include? sim
22
+ @@default = sym
23
+ end
24
+
25
+ def Logger.register(options = {})
26
+ @@loggers[options[:name]] = options[:instance]
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ Dir[File.dirname(__FILE__) + '/*.rb'].sort.each { |file| require file unless File.basename(file) == 'init.rb' }
2
+
3
+ module Sc4ry
4
+ module Notifiers
5
+ @@notifiers_list = {:prometheus => {:class => Sc4ry::Notifiers::Prometheus, :config => {:url => 'http://localhost:9091'}},
6
+ :mattermost => {:class => Sc4ry::Notifiers::Mattermost, :config => {:url => 'http://localhost:9999', :token => "<CHANGE_ME>"}}
7
+ }
8
+
9
+ def Notifiers.list
10
+ return @@notifiers_list.keys
11
+ end
12
+
13
+ def Notifiers.get(options ={})
14
+ return @@notifiers_list[options[:name]]
15
+ end
16
+
17
+ def Notifiers.register(options)
18
+ raise ":name is mandatory" unless options[:name]
19
+ raise ":definition is mandatory" unless options[:definition]
20
+ @@notifiers_list[options[:name]] = options[:definition]
21
+ end
22
+
23
+ def Notifiers.config(options)
24
+ raise ":name is mandatory" unless options[:name]
25
+ raise ":config is mandatory" unless options[:config]
26
+ @@notifiers_list[options[:name]][:config] = options[:config]
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,35 @@
1
+ module Sc4ry
2
+ module Notifiers
3
+
4
+ class Mattermost
5
+
6
+ # send metrics to Prometheus PushGateway
7
+ # @return [Bool]
8
+ def Mattermost.notify(options = {})
9
+ config = Sc4ry::Notifiers.get({name: :mattermost})[:config]
10
+ status = options[:config][:status][:general]
11
+ circuit = options[:circuit]
12
+ status_map = {:open => 0, :half_open => 1, :closed => 2}
13
+
14
+ uri = URI.parse("#{config[:url]}/hooks/#{config[:token]}")
15
+ message = "notifying for circuit #{circuit.to_s}, state : #{status.to_s}."
16
+ if Sc4ry::Helpers::verify_service url: config[:url] then
17
+ request = ::Net::HTTP::Post.new(uri)
18
+ request.content_type = "application/json"
19
+ req_options = {
20
+ use_ssl: uri.scheme == "https",
21
+ }
22
+ payload = { "text" => "message : #{message } from #{Socket.gethostname}", "username" => "Sc4ry" }
23
+ Sc4ry::Helpers.log level: :debug, message: "Mattermost Notifier : #{message}"
24
+ request.body = ::JSON.dump(payload)
25
+ response = ::Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
26
+ http.request(request)
27
+ end
28
+
29
+ else
30
+ Sc4ry::Helpers.log level: :warn, message: "Mattermost Notifier : can't notify Mattermost not reachable."
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ module Sc4ry
2
+ module Notifiers
3
+
4
+
5
+ class Prometheus
6
+
7
+ @@registry = ::Prometheus::Client::Registry::new
8
+ @@metric_circuit_state = ::Prometheus::Client::Gauge.new(:cuircuit_state, docstring: 'Sc4ry metric : state of a circuit', labels: [:circuit])
9
+
10
+ @@registry.register(@@metric_circuit_state)
11
+
12
+
13
+
14
+ # send metrics to Prometheus PushGateway
15
+ # @return [Bool]
16
+ def Prometheus.notify(options = {})
17
+ @config = Sc4ry::Notifiers.get({name: :prometheus})[:config]
18
+ status = options[:config][:status][:general]
19
+ circuit = options[:circuit]
20
+ status_map = {:open => 0, :half_open => 1, :closed => 2}
21
+ if Sc4ry::Helpers::verify_service url: @config[:url] then
22
+
23
+ @@metric_circuit_state.set(status_map[status], labels: {circuit: circuit.to_s })
24
+ Sc4ry::Helpers.log level: :debug, message: "Prometheus Notifier : notifying for circuit #{circuit.to_s}, state : #{status.to_s}."
25
+
26
+ return ::Prometheus::Client::Push.new(job: "Sc4ry", instance: Socket.gethostname, gateway: @config[:url]).add(@@registry)
27
+ else
28
+ Sc4ry::Helpers.log level: :warn, message: "Prometheus Notifier : can't notify Push Gateway not reachable."
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,59 @@
1
+
2
+ module Sc4ry
3
+ class RunController
4
+
5
+ attr_reader :execution_time
6
+
7
+ def initialize(circuit = {})
8
+ @circuit = circuit
9
+ @execution_time = 0
10
+ @timeout = false
11
+ @failure = false
12
+ @overtime = false
13
+ end
14
+
15
+ def failed?
16
+ return @failure
17
+ end
18
+
19
+ def overtimed?
20
+ return @overtime
21
+ end
22
+
23
+ def timeout?
24
+ return @timeout
25
+ end
26
+
27
+
28
+ def run(options = {})
29
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
30
+ begin
31
+ if @circuit[:timeout] == true
32
+ Timeout::timeout(@circuit[:timeout_value]) do
33
+ options[:block].call
34
+ end
35
+ @timeout = false
36
+ else
37
+ options[:block].call
38
+ end
39
+ rescue Exception => e
40
+ @last_exception = e.class
41
+ if e.class == Timeout::Error then
42
+ @timeout = true
43
+ elsif @circuit[:exceptions].include? e.class
44
+ @failure = true
45
+ else
46
+ Sc4ry::Loggers.warning "skipped : #{@last_exception}"
47
+ end
48
+ end
49
+ @end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
50
+ @execution_time = @end_time - start_time
51
+ @overtime = @execution_time > @circuit[:max_time]
52
+ return {failure: @failure, overtime: @overtime, timeout: @timeout, execution_time: @execution_time, end_time: @end_time, last_exception: @last_exception}
53
+
54
+ end
55
+
56
+
57
+
58
+ end
59
+ end
@@ -0,0 +1,42 @@
1
+ module Sc4ry
2
+ class Store
3
+
4
+ @@current = :memory
5
+
6
+ extend Forwardable
7
+ include Singleton
8
+
9
+ @@backends = {:memory => {:class => Sc4ry::Backends::Memory},
10
+ :redis => {:class => Sc4ry::Backends::Redis, :config => {:host => 'localhost', :port => 6379, :db => 10 }}}
11
+
12
+ attr_reader :be
13
+ def_delegators :@be, :put, :get, :flush, :exist?, :del, :list
14
+
15
+ def initialize
16
+ change_backend name: @@current
17
+ end
18
+
19
+ def current
20
+ return @@current
21
+ end
22
+
23
+ def change_backend(options)
24
+ @@current = options[:name]
25
+ @be = @@backends[@@current][:class]::new(@@backends[@@current][:config])
26
+ end
27
+
28
+ def register_backend(options)
29
+ raise ":name is mandatory" unless options[:name]
30
+ raise ":definition is mandatory" unless options[:definition]
31
+ @@backends[options[:name]] = options[:definition]
32
+ end
33
+
34
+ def config_backend(options)
35
+ raise ":name is mandatory" unless options[:name]
36
+ raise ":config is mandatory" unless options[:config]
37
+ @@backends[options[:name]][:config] = options[:config]
38
+ end
39
+
40
+
41
+ end
42
+ end
@@ -0,0 +1,3 @@
1
+ module Sc4ry
2
+ VERSION = "0.1.0"
3
+ end
data/lib/sc4ry.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "sc4ry/version"
2
+ require "sc4ry/dependencies"
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
data/sc4ry.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ require_relative 'lib/sc4ry/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sc4ry"
5
+ spec.version = Sc4ry::VERSION
6
+ spec.authors = ["Romain GEORGES"]
7
+ spec.email = ["romain.georges@orange.com"]
8
+
9
+ spec.summary = %q{Sc4Ry is Simple Circuitbreaker 4 RubY}
10
+ spec.description = %q{Sc4ry provide the design pattern Circuit breaker for your application.}
11
+ spec.homepage = "https://github.com/Ultragreen/sc4ry"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
14
+
15
+
16
+ # Specify which files should be added to the gem when it is released.
17
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.require_paths = ["lib"]
22
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sc4ry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Romain GEORGES
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-02-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Sc4ry provide the design pattern Circuit breaker for your application.
14
+ email:
15
+ - romain.georges@orange.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".gitignore"
21
+ - ".rspec"
22
+ - Gemfile
23
+ - LICENSE.txt
24
+ - README.md
25
+ - Rakefile
26
+ - bin/console
27
+ - bin/setup
28
+ - lib/sc4ry.rb
29
+ - lib/sc4ry/backends/init.rb
30
+ - lib/sc4ry/backends/memory.rb
31
+ - lib/sc4ry/backends/redis.rb
32
+ - lib/sc4ry/circuits.rb
33
+ - lib/sc4ry/dependencies.rb
34
+ - lib/sc4ry/exporters/init.rb
35
+ - lib/sc4ry/helpers.rb
36
+ - lib/sc4ry/logger.rb
37
+ - lib/sc4ry/notifiers/init.rb
38
+ - lib/sc4ry/notifiers/mattermost.rb
39
+ - lib/sc4ry/notifiers/prometheus.rb
40
+ - lib/sc4ry/run_controller.rb
41
+ - lib/sc4ry/store.rb
42
+ - lib/sc4ry/version.rb
43
+ - sc4ry.gemspec
44
+ homepage: https://github.com/Ultragreen/sc4ry
45
+ licenses:
46
+ - MIT
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 2.3.0
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubygems_version: 3.1.2
64
+ signing_key:
65
+ specification_version: 4
66
+ summary: Sc4Ry is Simple Circuitbreaker 4 RubY
67
+ test_files: []