cyclone_lariat 0.4.0 → 1.0.0.rc2
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 +5 -5
 - data/.github/workflows/gem-push.yml +4 -4
 - data/.rubocop.yml +9 -5
 - data/CHANGELOG.md +7 -1
 - data/Gemfile.lock +123 -21
 - data/Guardfile +42 -0
 - data/README.md +420 -223
 - data/bin/cyclone_lariat +75 -43
 - data/cyclone_lariat.gemspec +10 -3
 - data/lib/cyclone_lariat/clients/abstract.rb +40 -0
 - data/lib/cyclone_lariat/clients/sns.rb +163 -0
 - data/lib/cyclone_lariat/clients/sqs.rb +114 -0
 - data/lib/cyclone_lariat/core.rb +21 -0
 - data/lib/cyclone_lariat/errors.rb +16 -0
 - data/lib/cyclone_lariat/fake.rb +19 -0
 - data/lib/cyclone_lariat/generators/command.rb +53 -0
 - data/lib/cyclone_lariat/generators/event.rb +52 -0
 - data/lib/cyclone_lariat/generators/queue.rb +30 -0
 - data/lib/cyclone_lariat/generators/topic.rb +29 -0
 - data/lib/cyclone_lariat/messages/v1/abstract.rb +139 -0
 - data/lib/cyclone_lariat/messages/v1/command.rb +20 -0
 - data/lib/cyclone_lariat/messages/v1/event.rb +20 -0
 - data/lib/cyclone_lariat/messages/v1/validator.rb +31 -0
 - data/lib/cyclone_lariat/messages/v2/abstract.rb +149 -0
 - data/lib/cyclone_lariat/messages/v2/command.rb +20 -0
 - data/lib/cyclone_lariat/messages/v2/event.rb +20 -0
 - data/lib/cyclone_lariat/messages/v2/validator.rb +39 -0
 - data/lib/cyclone_lariat/middleware.rb +9 -6
 - data/lib/cyclone_lariat/migration.rb +54 -117
 - data/lib/cyclone_lariat/options.rb +52 -0
 - data/lib/cyclone_lariat/presenters/graph.rb +54 -0
 - data/lib/cyclone_lariat/presenters/queues.rb +41 -0
 - data/lib/cyclone_lariat/presenters/subscriptions.rb +34 -0
 - data/lib/cyclone_lariat/presenters/topics.rb +40 -0
 - data/lib/cyclone_lariat/publisher.rb +25 -0
 - data/lib/cyclone_lariat/repo/active_record/messages.rb +92 -0
 - data/lib/cyclone_lariat/repo/active_record/versions.rb +28 -0
 - data/lib/cyclone_lariat/repo/messages.rb +43 -0
 - data/lib/cyclone_lariat/repo/messages_mapper.rb +49 -0
 - data/lib/cyclone_lariat/repo/sequel/messages.rb +73 -0
 - data/lib/cyclone_lariat/repo/sequel/versions.rb +28 -0
 - data/lib/cyclone_lariat/repo/versions.rb +42 -0
 - data/lib/cyclone_lariat/resources/queue.rb +167 -0
 - data/lib/cyclone_lariat/resources/topic.rb +132 -0
 - data/lib/cyclone_lariat/services/migrate.rb +51 -0
 - data/lib/cyclone_lariat/services/rollback.rb +51 -0
 - data/lib/cyclone_lariat/version.rb +1 -1
 - data/lib/cyclone_lariat.rb +5 -11
 - data/lib/tasks/console.rake +1 -1
 - data/lib/tasks/cyclone_lariat.rake +10 -12
 - data/lib/tasks/db.rake +0 -15
 - metadata +127 -27
 - data/config/db.example.rb +0 -9
 - data/config/initializers/sequel.rb +0 -7
 - data/db/migrate/01_add_uuid_extensions.rb +0 -15
 - data/db/migrate/02_add_events.rb +0 -19
 - data/db/migrate/03_add_versions.rb +0 -9
 - data/docs/_imgs/graphviz_01.png +0 -0
 - data/docs/_imgs/graphviz_02.png +0 -0
 - data/docs/_imgs/graphviz_03.png +0 -0
 - data/docs/_imgs/lariat.jpg +0 -0
 - data/docs/_imgs/logic.png +0 -0
 - data/docs/_imgs/sqs_sns_diagram.png +0 -0
 - data/lib/cyclone_lariat/abstract/client.rb +0 -112
 - data/lib/cyclone_lariat/abstract/message.rb +0 -98
 - data/lib/cyclone_lariat/command.rb +0 -13
 - data/lib/cyclone_lariat/configure.rb +0 -15
 - data/lib/cyclone_lariat/event.rb +0 -13
 - data/lib/cyclone_lariat/messages_mapper.rb +0 -46
 - data/lib/cyclone_lariat/messages_repo.rb +0 -60
 - data/lib/cyclone_lariat/queue.rb +0 -147
 - data/lib/cyclone_lariat/sns_client.rb +0 -149
 - data/lib/cyclone_lariat/sqs_client.rb +0 -93
 - data/lib/cyclone_lariat/topic.rb +0 -113
 
| 
         @@ -0,0 +1,73 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'cyclone_lariat/messages/v1/event'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'cyclone_lariat/messages/v1/command'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'cyclone_lariat/repo/messages_mapper'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 8 
     | 
    
         
            +
              module Repo
         
     | 
| 
      
 9 
     | 
    
         
            +
                module Sequel
         
     | 
| 
      
 10 
     | 
    
         
            +
                  class Messages
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attr_reader :dataset
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def initialize(dataset)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      @dataset = dataset
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    def enabled?
         
     | 
| 
      
 18 
     | 
    
         
            +
                      !dataset.nil?
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    def disabled?
         
     | 
| 
      
 22 
     | 
    
         
            +
                      dataset.nil?
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                    def create(msg)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      dataset.insert MessagesMapper.to_row(msg)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    def exists?(uuid:)
         
     | 
| 
      
 30 
     | 
    
         
            +
                      dataset.where(uuid: uuid).limit(1).any?
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    def processed!(uuid:, error: nil)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      data = { processed_at: ::Sequel.function(:NOW) }
         
     | 
| 
      
 35 
     | 
    
         
            +
                      data.merge!(client_error_message: error.message, client_error_details: JSON.generate(error.details)) if error
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                      !dataset.where(uuid: uuid).update(data).zero?
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    def find(uuid:)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      row = dataset.where(uuid: uuid).first
         
     | 
| 
      
 42 
     | 
    
         
            +
                      return if row.nil?
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      build MessagesMapper.from_row(row)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    def each_unprocessed
         
     | 
| 
      
 48 
     | 
    
         
            +
                      dataset.where(processed_at: nil).each do |row|
         
     | 
| 
      
 49 
     | 
    
         
            +
                        msg = build MessagesMapper.from_row(row)
         
     | 
| 
      
 50 
     | 
    
         
            +
                        yield(msg)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    def each_with_client_errors
         
     | 
| 
      
 55 
     | 
    
         
            +
                      dataset.where { (processed_at !~ nil) & (client_error_message !~ nil) }.each do |row|
         
     | 
| 
      
 56 
     | 
    
         
            +
                        msg = build MessagesMapper.from_row(row)
         
     | 
| 
      
 57 
     | 
    
         
            +
                        yield(msg)
         
     | 
| 
      
 58 
     | 
    
         
            +
                      end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    private
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                    def build(raw)
         
     | 
| 
      
 64 
     | 
    
         
            +
                      case kind = raw.delete(:kind)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      when 'event'   then CycloneLariat::Messages::V1::Event.wrap raw
         
     | 
| 
      
 66 
     | 
    
         
            +
                      when 'command' then CycloneLariat::Messages::V1::Command.wrap raw
         
     | 
| 
      
 67 
     | 
    
         
            +
                      else raise ArgumentError, "Unknown kind `#{kind}` of message"
         
     | 
| 
      
 68 
     | 
    
         
            +
                      end
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Repo
         
     | 
| 
      
 5 
     | 
    
         
            +
                module Sequel
         
     | 
| 
      
 6 
     | 
    
         
            +
                  class Versions
         
     | 
| 
      
 7 
     | 
    
         
            +
                    attr_reader :dataset
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    def initialize(dataset)
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @dataset = dataset
         
     | 
| 
      
 11 
     | 
    
         
            +
                    end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    def add(version)
         
     | 
| 
      
 14 
     | 
    
         
            +
                      dataset.insert(version: version)
         
     | 
| 
      
 15 
     | 
    
         
            +
                      true
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    def remove(version)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      dataset.filter(version: version).delete.positive?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    def all
         
     | 
| 
      
 23 
     | 
    
         
            +
                      dataset.all
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'forwardable'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'luna_park/extensions/injector'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'cyclone_lariat/core'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'cyclone_lariat/repo/sequel/versions'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'cyclone_lariat/repo/active_record/versions'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 10 
     | 
    
         
            +
              module Repo
         
     | 
| 
      
 11 
     | 
    
         
            +
                class Versions
         
     | 
| 
      
 12 
     | 
    
         
            +
                  include LunaPark::Extensions::Injector
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  attr_reader :config
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  dependency(:sequel_versions_class) { Repo::Sequel::Versions }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  dependency(:active_record_versions_class) { Repo::ActiveRecord::Versions }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  extend Forwardable
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def_delegators :driver, :add, :remove, :all
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def initialize(**options)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @config = CycloneLariat::Options.wrap(options).merge!(CycloneLariat.config)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def driver
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @driver ||= select(driver: config.driver)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  private
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  def select(driver:)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    case driver
         
     | 
| 
      
 35 
     | 
    
         
            +
                    when :sequel then sequel_versions_class.new(config.versions_dataset)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    when :active_record then active_record_versions_class.new(config.versions_dataset)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    else raise ArgumentError, "Undefined driver `#{driver}`"
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,167 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'uri'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Resources
         
     | 
| 
      
 7 
     | 
    
         
            +
                class Queue
         
     | 
| 
      
 8 
     | 
    
         
            +
                  SNS_SUFFIX = :queue
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :instance, :kind, :region, :dest, :account_id, :publisher, :type, :fifo, :content_based_deduplication
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(instance:, kind:, region:, dest:, account_id:, publisher:, type:, fifo:, content_based_deduplication: nil, tags: nil, name: nil)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @instance  = instance
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @kind      = kind
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @region    = region
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @dest      = dest
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @account_id = account_id
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @publisher = publisher
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @type      = type
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @fifo      = fifo
         
     | 
| 
      
 21 
     | 
    
         
            +
                    @tags      = tags
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @name      = name
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @content_based_deduplication = content_based_deduplication
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def arn
         
     | 
| 
      
 27 
     | 
    
         
            +
                    ['arn', 'aws', 'sqs', region, account_id, name].join ':'
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # Url example:
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #  https://sqs.eu-west-1.amazonaws.com/247606935658/stage-event-queue
         
     | 
| 
      
 33 
     | 
    
         
            +
                  def url
         
     | 
| 
      
 34 
     | 
    
         
            +
                    "https://sqs.#{region}.amazonaws.com/#{account_id}/#{name}"
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def custom?
         
     | 
| 
      
 38 
     | 
    
         
            +
                    !standard?
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def standard?
         
     | 
| 
      
 42 
     | 
    
         
            +
                    instance && kind && publisher && type && true
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @name ||= begin
         
     | 
| 
      
 47 
     | 
    
         
            +
                      name = [instance, kind, SNS_SUFFIX, publisher, type, dest].compact.join '-'
         
     | 
| 
      
 48 
     | 
    
         
            +
                      name += '.fifo' if fifo
         
     | 
| 
      
 49 
     | 
    
         
            +
                      name
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  alias to_s name
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  def topic?
         
     | 
| 
      
 56 
     | 
    
         
            +
                    false
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  def queue?
         
     | 
| 
      
 60 
     | 
    
         
            +
                    true
         
     | 
| 
      
 61 
     | 
    
         
            +
                  end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
                  def protocol
         
     | 
| 
      
 64 
     | 
    
         
            +
                    'sqs'
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  def attributes
         
     | 
| 
      
 68 
     | 
    
         
            +
                    attrs = {}
         
     | 
| 
      
 69 
     | 
    
         
            +
                    attrs['FifoQueue']                 = 'true' if fifo
         
     | 
| 
      
 70 
     | 
    
         
            +
                    attrs['ContentBasedDeduplication'] = 'true' if content_based_deduplication
         
     | 
| 
      
 71 
     | 
    
         
            +
                    attrs
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 75 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 76 
     | 
    
         
            +
                    # Name example: test-event-queue-cyclone_lariat-note_added.fifo
         
     | 
| 
      
 77 
     | 
    
         
            +
                    # instance: teste
         
     | 
| 
      
 78 
     | 
    
         
            +
                    # kind: event
         
     | 
| 
      
 79 
     | 
    
         
            +
                    # publisher: cyclone_lariat
         
     | 
| 
      
 80 
     | 
    
         
            +
                    # type: note_added
         
     | 
| 
      
 81 
     | 
    
         
            +
                    # dest: nil
         
     | 
| 
      
 82 
     | 
    
         
            +
                    # fifo: true
         
     | 
| 
      
 83 
     | 
    
         
            +
                    def from_name(name, region:, account_id:)
         
     | 
| 
      
 84 
     | 
    
         
            +
                      is_fifo_array  = name.split('.')
         
     | 
| 
      
 85 
     | 
    
         
            +
                      full_name      = is_fifo_array[0]
         
     | 
| 
      
 86 
     | 
    
         
            +
                      fifo_suffix    = is_fifo_array[-1]
         
     | 
| 
      
 87 
     | 
    
         
            +
                      suffix_exists  = fifo_suffix != full_name
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                      if suffix_exists && fifo_suffix != 'fifo'
         
     | 
| 
      
 90 
     | 
    
         
            +
                        raise ArgumentError, "Queue name #{name} consists unexpected suffix #{fifo_suffix}"
         
     | 
| 
      
 91 
     | 
    
         
            +
                      end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                      fifo        = suffix_exists
         
     | 
| 
      
 94 
     | 
    
         
            +
                      queue_array = full_name.split('-')
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                      raise ArgumentError, "Topic name should consists `#{SNS_SUFFIX}`" unless queue_array[2] != SNS_SUFFIX
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                      queue_array.clear if queue_array.size < 5
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                      new(
         
     | 
| 
      
 101 
     | 
    
         
            +
                        instance: queue_array[0], kind: queue_array[1], region: region, dest: queue_array[5],
         
     | 
| 
      
 102 
     | 
    
         
            +
                        account_id: account_id, publisher: queue_array[3], type: queue_array[4], fifo: fifo, name: name
         
     | 
| 
      
 103 
     | 
    
         
            +
                      )
         
     | 
| 
      
 104 
     | 
    
         
            +
                    end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 107 
     | 
    
         
            +
                    # URL example: https://sqs.eu-west-1.amazonaws.com/247606935658/test-event-queue-cyclone_lariat-note_added.fifo
         
     | 
| 
      
 108 
     | 
    
         
            +
                    # url_array[0]  => https
         
     | 
| 
      
 109 
     | 
    
         
            +
                    # host_array[0] => sqs
         
     | 
| 
      
 110 
     | 
    
         
            +
                    # host_array[1] => eu-west-1
         
     | 
| 
      
 111 
     | 
    
         
            +
                    # url_array[3]  => 247606935658 # account_id
         
     | 
| 
      
 112 
     | 
    
         
            +
                    # url_array[4]  => test-event-queue-cyclone_lariat-note_added.fifo # name
         
     | 
| 
      
 113 
     | 
    
         
            +
                    def from_url(url)
         
     | 
| 
      
 114 
     | 
    
         
            +
                      raise ArgumentError, 'Url is not http format' unless url =~ URI::DEFAULT_PARSER.make_regexp
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                      url_array = url.split('/')
         
     | 
| 
      
 117 
     | 
    
         
            +
                      raise ArgumentError, 'Url should start from https' unless url_array[0] == 'https:'
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                      host_array = url_array[2].split('.')
         
     | 
| 
      
 120 
     | 
    
         
            +
                      raise ArgumentError, 'It is not queue url' unless host_array[0] == 'sqs'
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                      from_name(url_array[4], region: host_array[1], account_id: url_array[3])
         
     | 
| 
      
 123 
     | 
    
         
            +
                    end
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 126 
     | 
    
         
            +
                    # Arn example: "arn:aws:sqs:eu-west-1:247606935658:custom_queue"
         
     | 
| 
      
 127 
     | 
    
         
            +
                    # arn_array[0] => 'arn'
         
     | 
| 
      
 128 
     | 
    
         
            +
                    # arn_array[1] => 'aws'
         
     | 
| 
      
 129 
     | 
    
         
            +
                    # arn_array[2] => 'sqs'
         
     | 
| 
      
 130 
     | 
    
         
            +
                    # arn_array[3] => 'eu-west-1'     # region
         
     | 
| 
      
 131 
     | 
    
         
            +
                    # arn_array[4] => '247606935658'  # account_id
         
     | 
| 
      
 132 
     | 
    
         
            +
                    # arn_array[5] => 'alexey_test2'  # name
         
     | 
| 
      
 133 
     | 
    
         
            +
                    def from_arn(arn)
         
     | 
| 
      
 134 
     | 
    
         
            +
                      arn_array = arn.split(':')
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                      raise ArgumentError, "Arn `#{arn}` should consists `arn`" unless arn_array[0] == 'arn'
         
     | 
| 
      
 137 
     | 
    
         
            +
                      raise ArgumentError, "Arn `#{arn}` should consists `aws`" unless arn_array[1] == 'aws'
         
     | 
| 
      
 138 
     | 
    
         
            +
                      raise ArgumentError, "Arn `#{arn}` should consists `sqs`" unless arn_array[2] == 'sqs'
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                      from_name(arn_array[5], region: arn_array[3], account_id: arn_array[4])
         
     | 
| 
      
 141 
     | 
    
         
            +
                    end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  def tags
         
     | 
| 
      
 145 
     | 
    
         
            +
                    @tags ||= begin
         
     | 
| 
      
 146 
     | 
    
         
            +
                      if standard?
         
     | 
| 
      
 147 
     | 
    
         
            +
                        {
         
     | 
| 
      
 148 
     | 
    
         
            +
                          'standard' => 'true',
         
     | 
| 
      
 149 
     | 
    
         
            +
                          'instance' => String(instance),
         
     | 
| 
      
 150 
     | 
    
         
            +
                          'kind' => String(kind),
         
     | 
| 
      
 151 
     | 
    
         
            +
                          'publisher' => String(publisher),
         
     | 
| 
      
 152 
     | 
    
         
            +
                          'type' => String(type),
         
     | 
| 
      
 153 
     | 
    
         
            +
                          'dest' => dest ? String(dest) : 'undefined',
         
     | 
| 
      
 154 
     | 
    
         
            +
                          'fifo' => fifo ? 'true' : 'false'
         
     | 
| 
      
 155 
     | 
    
         
            +
                        }
         
     | 
| 
      
 156 
     | 
    
         
            +
                      else
         
     | 
| 
      
 157 
     | 
    
         
            +
                        {
         
     | 
| 
      
 158 
     | 
    
         
            +
                          'standard' => 'false',
         
     | 
| 
      
 159 
     | 
    
         
            +
                          'name' => String(name),
         
     | 
| 
      
 160 
     | 
    
         
            +
                          'fifo' => fifo ? 'true' : 'false'
         
     | 
| 
      
 161 
     | 
    
         
            +
                        }
         
     | 
| 
      
 162 
     | 
    
         
            +
                      end
         
     | 
| 
      
 163 
     | 
    
         
            +
                    end
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
                end
         
     | 
| 
      
 166 
     | 
    
         
            +
              end
         
     | 
| 
      
 167 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,132 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Resources
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Topic
         
     | 
| 
      
 6 
     | 
    
         
            +
                  SNS_SUFFIX = :fanout
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :instance, :kind, :region, :account_id, :publisher, :type, :fifo, :content_based_deduplication
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(instance:, kind:, region:, account_id:, publisher:, type:, fifo:, content_based_deduplication: nil, tags: nil, name: nil)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @instance  = instance
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @kind      = kind
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @region    = region
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @account_id = account_id
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @publisher = publisher
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @type      = type
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @fifo      = fifo
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @tags      = tags
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @name      = name
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @content_based_deduplication = content_based_deduplication
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def arn
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ['arn', 'aws', 'sns', region, account_id, to_s].join ':'
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def custom?
         
     | 
| 
      
 28 
     | 
    
         
            +
                    !standard?
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def standard?
         
     | 
| 
      
 32 
     | 
    
         
            +
                    return false unless instance && kind && publisher && type
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    true
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  def name
         
     | 
| 
      
 38 
     | 
    
         
            +
                    @name ||= begin
         
     | 
| 
      
 39 
     | 
    
         
            +
                      name = [instance, kind, SNS_SUFFIX, publisher, type].compact.join '-'
         
     | 
| 
      
 40 
     | 
    
         
            +
                      name += '.fifo' if fifo
         
     | 
| 
      
 41 
     | 
    
         
            +
                      name
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  def attributes
         
     | 
| 
      
 46 
     | 
    
         
            +
                    attrs = {}
         
     | 
| 
      
 47 
     | 
    
         
            +
                    attrs['FifoTopic']                 = 'true' if fifo
         
     | 
| 
      
 48 
     | 
    
         
            +
                    attrs['ContentBasedDeduplication'] = 'true' if content_based_deduplication
         
     | 
| 
      
 49 
     | 
    
         
            +
                    attrs
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def topic?
         
     | 
| 
      
 53 
     | 
    
         
            +
                    true
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                  def queue?
         
     | 
| 
      
 57 
     | 
    
         
            +
                    false
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  def protocol
         
     | 
| 
      
 61 
     | 
    
         
            +
                    'sns'
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  alias to_s name
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def ==(other)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    arn == other.arn
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 71 
     | 
    
         
            +
                    def from_name(name, region:, account_id:)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      is_fifo_array  = name.split('.')
         
     | 
| 
      
 73 
     | 
    
         
            +
                      full_name      = is_fifo_array[0]
         
     | 
| 
      
 74 
     | 
    
         
            +
                      fifo_suffix    = is_fifo_array[-1]
         
     | 
| 
      
 75 
     | 
    
         
            +
                      suffix_exists  = fifo_suffix != full_name
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                      if suffix_exists && fifo_suffix != 'fifo'
         
     | 
| 
      
 78 
     | 
    
         
            +
                        raise ArgumentError, "Topic name #{name} consists unexpected suffix #{fifo_suffix}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                      end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                      fifo = suffix_exists
         
     | 
| 
      
 82 
     | 
    
         
            +
                      topic_array = full_name.split('-')
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                      raise ArgumentError, "Topic name should consists `#{SNS_SUFFIX}`" unless topic_array[2] != SNS_SUFFIX
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                      topic_array.clear if topic_array.size < 5
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                      new(
         
     | 
| 
      
 89 
     | 
    
         
            +
                        instance: topic_array[0],
         
     | 
| 
      
 90 
     | 
    
         
            +
                        kind: topic_array[1],
         
     | 
| 
      
 91 
     | 
    
         
            +
                        publisher: topic_array[3],
         
     | 
| 
      
 92 
     | 
    
         
            +
                        type: topic_array[4],
         
     | 
| 
      
 93 
     | 
    
         
            +
                        region: region,
         
     | 
| 
      
 94 
     | 
    
         
            +
                        account_id: account_id,
         
     | 
| 
      
 95 
     | 
    
         
            +
                        fifo: fifo,
         
     | 
| 
      
 96 
     | 
    
         
            +
                        name: name
         
     | 
| 
      
 97 
     | 
    
         
            +
                      )
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    def from_arn(arn)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      arn_array = arn.split(':')
         
     | 
| 
      
 102 
     | 
    
         
            +
                      raise ArgumentError, 'Arn should consists `arn`' unless arn_array[0] == 'arn'
         
     | 
| 
      
 103 
     | 
    
         
            +
                      raise ArgumentError, 'Arn should consists `aws`' unless arn_array[1] == 'aws'
         
     | 
| 
      
 104 
     | 
    
         
            +
                      raise ArgumentError, 'Arn should consists `sns`' unless arn_array[2] == 'sns'
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                      from_name(arn_array[5], region: arn_array[3], account_id: arn_array[4])
         
     | 
| 
      
 107 
     | 
    
         
            +
                    end
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                  def tags
         
     | 
| 
      
 111 
     | 
    
         
            +
                    @tags ||= begin
         
     | 
| 
      
 112 
     | 
    
         
            +
                      if standard?
         
     | 
| 
      
 113 
     | 
    
         
            +
                        [
         
     | 
| 
      
 114 
     | 
    
         
            +
                          { key: 'standard',  value: 'true' },
         
     | 
| 
      
 115 
     | 
    
         
            +
                          { key: 'instance',  value: String(instance) },
         
     | 
| 
      
 116 
     | 
    
         
            +
                          { key: 'kind',      value: String(kind) },
         
     | 
| 
      
 117 
     | 
    
         
            +
                          { key: 'publisher', value: String(publisher) },
         
     | 
| 
      
 118 
     | 
    
         
            +
                          { key: 'type',      value: String(type) },
         
     | 
| 
      
 119 
     | 
    
         
            +
                          { key: 'fifo',      value: fifo ? 'true' : 'false' }
         
     | 
| 
      
 120 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 121 
     | 
    
         
            +
                      else
         
     | 
| 
      
 122 
     | 
    
         
            +
                        [
         
     | 
| 
      
 123 
     | 
    
         
            +
                          { key: 'standard',  value: 'false' },
         
     | 
| 
      
 124 
     | 
    
         
            +
                          { key: 'name',      value: String(name) },
         
     | 
| 
      
 125 
     | 
    
         
            +
                          { key: 'fifo',      value: fifo ? 'true' : 'false' }
         
     | 
| 
      
 126 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 127 
     | 
    
         
            +
                      end
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
                  end
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
              end
         
     | 
| 
      
 132 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Services
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Migrate
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :repo, :dir
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(repo:, dir:)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @repo = repo
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @dir = dir
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def call
         
     | 
| 
      
 14 
     | 
    
         
            +
                    alert('No one migration exists') if !Dir.exist?(dir) || Dir.empty?(dir)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    output = []
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    migration_paths.each do |path|
         
     | 
| 
      
 18 
     | 
    
         
            +
                      filename = File.basename(path, '.rb')
         
     | 
| 
      
 19 
     | 
    
         
            +
                      version, title = filename.split('_', 2)
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                      next if existed_migrations.include? version.to_i
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                      class_name = title.split('_').collect(&:capitalize).join
         
     | 
| 
      
 24 
     | 
    
         
            +
                      output << "Up - #{version} #{class_name} #{path}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                      require_relative Pathname.new(Dir.pwd) + Pathname.new(path)
         
     | 
| 
      
 26 
     | 
    
         
            +
                      Object.const_get(class_name).new.up
         
     | 
| 
      
 27 
     | 
    
         
            +
                      repo.add(version)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    output
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  # Sorted by timestamp
         
     | 
| 
      
 36 
     | 
    
         
            +
                  def migration_paths
         
     | 
| 
      
 37 
     | 
    
         
            +
                    # lariat/migrate/1668161620_many_to_one.rb
         
     | 
| 
      
 38 
     | 
    
         
            +
                    Dir.glob("#{dir}/*.rb").sort_by do |file_path|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      # 1668161620_many_to_one.rb
         
     | 
| 
      
 40 
     | 
    
         
            +
                      file_name = file_path.split('/')[-1]
         
     | 
| 
      
 41 
     | 
    
         
            +
                      # 1668161620
         
     | 
| 
      
 42 
     | 
    
         
            +
                      file_name.split('_').first.to_i
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  def existed_migrations
         
     | 
| 
      
 47 
     | 
    
         
            +
                    @existed_migrations ||= repo.all.map { |row| row[:version] }
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module CycloneLariat
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Services
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Rollback
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :repo, :dir
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(repo:, dir:)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @repo = repo
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @dir = dir
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def call(version = nil)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    version ||= existed_migrations[-1]
         
     | 
| 
      
 15 
     | 
    
         
            +
                    output = []
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    paths_of_downgrades(version).each do |path|
         
     | 
| 
      
 18 
     | 
    
         
            +
                      filename       = File.basename(path, '.rb')
         
     | 
| 
      
 19 
     | 
    
         
            +
                      version, title = filename.split('_', 2)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      class_name     = title.split('_').collect(&:capitalize).join
         
     | 
| 
      
 21 
     | 
    
         
            +
                      output << "Down - #{version} #{class_name} #{path}"
         
     | 
| 
      
 22 
     | 
    
         
            +
                      require_relative Pathname.new(Dir.pwd) + Pathname.new(path)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      Object.const_get(class_name).new.down
         
     | 
| 
      
 24 
     | 
    
         
            +
                      repo.remove(version)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    output
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def existed_migrations
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @existed_migrations ||= repo.all.map { |row| row[:version] }.sort
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def paths_of_downgrades(version)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    migrations_to_downgrade = existed_migrations.select { |migration| migration >= version }
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    paths = []
         
     | 
| 
      
 38 
     | 
    
         
            +
                    migrations_to_downgrade.each do |migration|
         
     | 
| 
      
 39 
     | 
    
         
            +
                      path = Pathname.new(Dir.pwd) + Pathname.new(dir)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      founded = Dir.glob("#{path}/#{migration}_*.rb")
         
     | 
| 
      
 41 
     | 
    
         
            +
                      raise "Could not found migration: `#{migration}` in #{path}" if founded.empty?
         
     | 
| 
      
 42 
     | 
    
         
            +
                      raise "Found lot of migration: `#{migration}` in #{path}"    if founded.size > 1
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                      paths += founded
         
     | 
| 
      
 45 
     | 
    
         
            +
                    end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    paths
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/cyclone_lariat.rb
    CHANGED
    
    | 
         @@ -1,13 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
             
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            require_relative 'cyclone_lariat/messages_repo'
         
     | 
| 
       9 
     | 
    
         
            -
            require_relative 'cyclone_lariat/migration'
         
     | 
| 
       10 
     | 
    
         
            -
            require_relative 'cyclone_lariat/middleware'
         
     | 
| 
       11 
     | 
    
         
            -
            require_relative 'cyclone_lariat/version'
         
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
            module CycloneLariat; end
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'cyclone_lariat/version'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'cyclone_lariat/core'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'cyclone_lariat/middleware'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'cyclone_lariat/migration'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'cyclone_lariat/publisher'
         
     | 
    
        data/lib/tasks/console.rake
    CHANGED
    
    | 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            desc 'IRB console with required CycloneLariat'
         
     | 
| 
       4 
4 
     | 
    
         
             
            task :console do
         
     | 
| 
       5 
5 
     | 
    
         
             
              # require 'cyclone_lariat'
         
     | 
| 
       6 
     | 
    
         
            -
               
     | 
| 
      
 6 
     | 
    
         
            +
              require 'cyclone_lariat'
         
     | 
| 
       7 
7 
     | 
    
         
             
              require 'irb'
         
     | 
| 
       8 
8 
     | 
    
         
             
              require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
       9 
9 
     | 
    
         
             
              # require_relative(init_file) if File.exists?(init_file)
         
     | 
| 
         @@ -3,42 +3,40 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'cyclone_lariat'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            namespace :cyclone_lariat do
         
     | 
| 
       6 
     | 
    
         
            -
              desc 'Migrate topics for  
     | 
| 
      
 6 
     | 
    
         
            +
              desc 'Migrate topics for SQS/SNS'
         
     | 
| 
       7 
7 
     | 
    
         
             
              task migrate: :config do
         
     | 
| 
       8 
     | 
    
         
            -
                require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
       9 
8 
     | 
    
         
             
                CycloneLariat::Migration.migrate
         
     | 
| 
       10 
9 
     | 
    
         
             
              end
         
     | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
              desc 'Rollback topics for  
     | 
| 
      
 11 
     | 
    
         
            +
              desc 'Rollback topics for SQS/SNS'
         
     | 
| 
       13 
12 
     | 
    
         
             
              task :rollback, [:version] => :config do |_, args|
         
     | 
| 
       14 
     | 
    
         
            -
                require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
       15 
13 
     | 
    
         
             
                target_version = args[:version] ? args[:version].to_i : nil
         
     | 
| 
       16 
14 
     | 
    
         
             
                CycloneLariat::Migration.rollback(target_version)
         
     | 
| 
       17 
15 
     | 
    
         
             
              end
         
     | 
| 
       18 
16 
     | 
    
         | 
| 
       19 
17 
     | 
    
         
             
              namespace :list do
         
     | 
| 
       20 
18 
     | 
    
         
             
                desc 'List all topics'
         
     | 
| 
       21 
     | 
    
         
            -
                task : 
     | 
| 
       22 
     | 
    
         
            -
                  require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
      
 19 
     | 
    
         
            +
                task topics: :config do
         
     | 
| 
       23 
20 
     | 
    
         
             
                  CycloneLariat::Migration.list_topics
         
     | 
| 
       24 
21 
     | 
    
         
             
                end
         
     | 
| 
       25 
22 
     | 
    
         | 
| 
       26 
23 
     | 
    
         
             
                desc 'List all queues'
         
     | 
| 
       27 
     | 
    
         
            -
                task : 
     | 
| 
       28 
     | 
    
         
            -
                  require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
      
 24 
     | 
    
         
            +
                task queues: :config do
         
     | 
| 
       29 
25 
     | 
    
         
             
                  CycloneLariat::Migration.list_queues
         
     | 
| 
       30 
26 
     | 
    
         
             
                end
         
     | 
| 
       31 
27 
     | 
    
         | 
| 
       32 
28 
     | 
    
         
             
                desc 'List all subscriptions'
         
     | 
| 
       33 
     | 
    
         
            -
                task : 
     | 
| 
       34 
     | 
    
         
            -
                  require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
      
 29 
     | 
    
         
            +
                task subscriptions: :config do
         
     | 
| 
       35 
30 
     | 
    
         
             
                  CycloneLariat::Migration.list_subscriptions
         
     | 
| 
       36 
31 
     | 
    
         
             
                end
         
     | 
| 
       37 
32 
     | 
    
         
             
              end
         
     | 
| 
       38 
33 
     | 
    
         | 
| 
       39 
34 
     | 
    
         
             
              desc 'Build graphviz graph for whole system'
         
     | 
| 
       40 
     | 
    
         
            -
              task : 
     | 
| 
       41 
     | 
    
         
            -
                require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
      
 35 
     | 
    
         
            +
              task graph: :config do
         
     | 
| 
       42 
36 
     | 
    
         
             
                CycloneLariat::Migration.build_graph
         
     | 
| 
       43 
37 
     | 
    
         
             
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              task :config do
         
     | 
| 
      
 40 
     | 
    
         
            +
                require_relative '../../config/initializers/cyclone_lariat'
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
       44 
42 
     | 
    
         
             
            end
         
     | 
    
        data/lib/tasks/db.rake
    CHANGED
    
    | 
         @@ -22,20 +22,6 @@ namespace :db do 
     | 
|
| 
       22 
22 
     | 
    
         
             
                puts "Database `#{DB_CONF[:database]}` successfully dropped" if system(cmd)
         
     | 
| 
       23 
23 
     | 
    
         
             
              end
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
              desc 'Apply migrate'
         
     | 
| 
       26 
     | 
    
         
            -
              task :migrate, [:version] => :config do |_, args|
         
     | 
| 
       27 
     | 
    
         
            -
                require 'logger'
         
     | 
| 
       28 
     | 
    
         
            -
                require 'sequel/core'
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                Sequel.extension :migration
         
     | 
| 
       31 
     | 
    
         
            -
                version = args[:version] ? args[:version].to_i : nil
         
     | 
| 
       32 
     | 
    
         
            -
                migrations_path = "#{__dir__}/../../db/migrate/"
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
                Sequel.connect(**DB_CONF, logger: Logger.new($stdout)) do |db|
         
     | 
| 
       35 
     | 
    
         
            -
                  Sequel::Migrator.run(db, migrations_path, target: version)
         
     | 
| 
       36 
     | 
    
         
            -
                end
         
     | 
| 
       37 
     | 
    
         
            -
              end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
25 
     | 
    
         
             
              desc 'Database console'
         
     | 
| 
       40 
26 
     | 
    
         
             
              task console: :config do
         
     | 
| 
       41 
27 
     | 
    
         
             
                cmd = "PGPASSWORD=#{DB_CONF[:password]} psql" \
         
     | 
| 
         @@ -50,6 +36,5 @@ namespace :db do 
     | 
|
| 
       50 
36 
     | 
    
         
             
              task :reset do
         
     | 
| 
       51 
37 
     | 
    
         
             
                Rake::Task['db:drop'].invoke
         
     | 
| 
       52 
38 
     | 
    
         
             
                Rake::Task['db:create'].invoke
         
     | 
| 
       53 
     | 
    
         
            -
                Rake::Task['db:migrate'].invoke
         
     | 
| 
       54 
39 
     | 
    
         
             
              end
         
     | 
| 
       55 
40 
     | 
    
         
             
            end
         
     |