aranha-rails 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +25 -0
  4. data/Gemfile +5 -0
  5. data/app/assets/javascripts/aranha/application.js +2 -0
  6. data/app/assets/stylesheets/aranha/application.css +5 -0
  7. data/app/controllers/aranha/addresses_controller.rb +8 -0
  8. data/app/controllers/aranha/processor_configurations_controller.rb +16 -0
  9. data/app/controllers/aranha/start_points_controller.rb +16 -0
  10. data/app/models/aranha/address/delayed_job.rb +39 -0
  11. data/app/models/aranha/address/processor.rb +24 -0
  12. data/app/models/aranha/address/scheduling.rb +49 -0
  13. data/app/models/aranha/address.rb +80 -0
  14. data/app/models/aranha/processor_configuration.rb +51 -0
  15. data/app/models/aranha/start_point.rb +47 -0
  16. data/config/initializers/aranha.rb +5 -0
  17. data/config/locales/en.yml +12 -0
  18. data/config/locales/pt-BR.yml +12 -0
  19. data/config/routes.rb +8 -0
  20. data/db/migrate/20171201021251_create_aranha_addresses.rb +15 -0
  21. data/db/migrate/20181125042102_add_extra_data_to_aranha_addresses.rb +9 -0
  22. data/db/migrate/20201128202212_create_aranha_start_points.rb +13 -0
  23. data/db/migrate/20210720023620_add_delayed_job_to_aranha_addresses.rb +7 -0
  24. data/db/migrate/20210721171416_add_tries_count_to_aranha_addresses.rb +7 -0
  25. data/db/migrate/20210721185222_add_last_error_to_aranha_addresses.rb +7 -0
  26. data/db/migrate/20210814220540_create_aranha_processor_configurations.rb +12 -0
  27. data/db/migrate/20210815160543_add_enabled_to_aranha_processor_configurations.rb +7 -0
  28. data/lib/aranha/rails/version.rb +1 -1
  29. data/spec/rubocop_spec.rb +3 -0
  30. data/spec/spec_helper.rb +4 -0
  31. metadata +36 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36ba45ae4efcdde7c87ec2826a8ae37457c791a7384b4fd3cbdd349f32fe9767
4
- data.tar.gz: fbda8a52654c3640017c0bf7e62cc5c7ef2dbf66d2c5f59d9083685629c78314
3
+ metadata.gz: a7f0c7237e3e9ca7d3f5ddc61973513d2a86750e88d96640879c5cd91a46be91
4
+ data.tar.gz: 59b99c087566e49e93e116d51a05f2c29406d8376640112d52f7c59184543de8
5
5
  SHA512:
6
- metadata.gz: 5aa3e496c87dae2659430b1fe08388a4b32087a5ff3cf5835c7327e43e2fd0e2b5c945a8e4911c29cdd99bd8aada31d0e1289bb11e9f962c170ec6c230e2b7a4
7
- data.tar.gz: cc60ef5294d2af9e2b0066d1cae61ec1c8aecd0d5eccfc005b61509282c7f39911fb9aef399c86b46c833c5a1ad7001f3fc75fa784bac60be17fb5e25864558f
6
+ metadata.gz: 80ec1e16b92e7ae0cb463f64c4f6f35b93876fb0987fc0a6ed9d3a57cb509fba35fcddeae40b6b16ba8901576e3f6da125c79e40b3d246b77887c90e8ba15bee
7
+ data.tar.gz: 82a5d76749efb28e26388b1af4cb2d9208915920124e6d6b881d58a1e598a56de989fb539da363a26d09827e96d6cd985f516815ba633ed38069e2eeefffa92e
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ require:
2
+ - rubocop-rails
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ TargetRubyVersion: 2.4
7
+ TargetRailsVersion: 5.1
8
+
9
+ Layout/LineLength:
10
+ Max: 100
11
+
12
+ Style/AsciiComments:
13
+ Enabled: false
14
+
15
+ Style/Documentation:
16
+ Enabled: false
17
+
18
+ Style/HashEachMethods:
19
+ Enabled: true
20
+
21
+ Style/HashTransformKeys:
22
+ Enabled: true
23
+
24
+ Style/HashTransformValues:
25
+ Enabled: true
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,2 @@
1
+ //= require_tree .
2
+ //= require active_scaffold
@@ -0,0 +1,5 @@
1
+ /*
2
+ *= require_tree .
3
+ *= require_self
4
+ *= require active_scaffold
5
+ */
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aranha
4
+ class AddressesController < ::ApplicationController
5
+ active_scaffold :'aranha/address' do |_conf|
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aranha
4
+ class ProcessorConfigurationsController < ::ApplicationController
5
+ before_action :configure_processor_class_options
6
+
7
+ active_scaffold :'aranha/processor_configuration' do |conf|
8
+ conf.columns[:processor_class].form_ui = :select
9
+ end
10
+
11
+ def configure_processor_class_options
12
+ active_scaffold_config.columns[:processor_class].options =
13
+ { options: ::Aranha::ProcessorConfiguration.processor_class_options }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aranha
4
+ class StartPointsController < ::ApplicationController
5
+ before_action :configure_processor_class_options
6
+
7
+ active_scaffold :'aranha/start_point' do |conf|
8
+ conf.columns[:processor_class].form_ui = :select
9
+ end
10
+
11
+ def configure_processor_class_options
12
+ active_scaffold_config.columns[:processor_class].options =
13
+ { options: ::Aranha::StartPoint.processor_class_options }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Aranha
6
+ class Address < ::ActiveRecord::Base
7
+ class DelayedJob
8
+ common_constructor :address_id
9
+
10
+ def perform
11
+ address_processor.successful? ? perform_on_success : perform_on_error
12
+ end
13
+
14
+ private
15
+
16
+ def address
17
+ address_processor.address
18
+ end
19
+
20
+ def perform_on_success
21
+ # Do nothing
22
+ end
23
+
24
+ def perform_on_error
25
+ address.update!(
26
+ tries_count: address.tries_count + 1,
27
+ last_error: address_processor.error.to_yaml
28
+ )
29
+ address.check_scheduling
30
+ end
31
+
32
+ def address_processor
33
+ @address_processor ||= ::Aranha::AddressProcessor.new(
34
+ ::Aranha::Address.find(address_id)
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Aranha
6
+ class Address < ::ActiveRecord::Base
7
+ module Processor
8
+ common_concern
9
+
10
+ module ClassMethods
11
+ # @return [Aranha::ProcessorConfiguration]
12
+ def default_processor_configuration
13
+ @default_processor_configuration ||= ::Aranha::ProcessorConfiguration.new
14
+ end
15
+ end
16
+
17
+ # @return [Aranha::ProcessorConfiguration]
18
+ def processor_configuration
19
+ ::Aranha::ProcessorConfiguration.find_by(processor_class: processor) ||
20
+ self.class.default_processor_configuration
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Aranha
6
+ class Address < ::ActiveRecord::Base
7
+ module Scheduling
8
+ common_concern
9
+
10
+ module ClassMethods
11
+ # @return [Array<Aranha::Address>]
12
+ def expired(time = ::Time.zone.now)
13
+ all.select { |record| record.expired?(time) }
14
+ end
15
+ end
16
+
17
+ def check_scheduling
18
+ ::ActiveRecord::Base.transaction do
19
+ return unless schedule?
20
+
21
+ job = ::Delayed::Job.enqueue(
22
+ ::Aranha::Address::DelayedJob.new(id),
23
+ queue: ::Aranha::Rails::Process::QUEUE
24
+ )
25
+ update!(delayed_job: job)
26
+ end
27
+ end
28
+
29
+ def expired?(time = ::Time.zone.now)
30
+ time >= (created_at + timeout)
31
+ end
32
+
33
+ def init_scheduling
34
+ update!(tries_count: 0, last_error: nil) unless processed?
35
+ check_scheduling
36
+ end
37
+
38
+ def allow_retry?
39
+ tries_count < ::Aranha::Processor::DEFAULT_MAX_TRIES
40
+ end
41
+
42
+ def schedule?
43
+ processed_at.blank? && allow_retry? && delayed_job.blank? && enabled?
44
+ end
45
+
46
+ delegate :enabled?, :timeout, to: :processor_configuration
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/yaml'
4
+ require 'delayed/backend/active_record'
5
+
6
+ module Aranha
7
+ class Address < ::ActiveRecord::Base
8
+ include ::EacRailsUtils::Models::InequalityQueries
9
+ include ::Aranha::Address::Processor
10
+ include ::Aranha::Address::Scheduling
11
+
12
+ add_inequality_queries(:created_at)
13
+
14
+ class << self
15
+ def sanitize_url(url)
16
+ if url.is_a?(Hash)
17
+ ::EacRubyUtils::Yaml.dump(url)
18
+ else
19
+ url.to_s
20
+ end
21
+ end
22
+ end
23
+
24
+ belongs_to :delayed_job, class_name: 'Delayed::Backend::ActiveRecord::Job', dependent: :destroy,
25
+ optional: true
26
+
27
+ validates :url, presence: true, uniqueness: true
28
+ validates :processor, presence: true
29
+ validates :tries_count, presence: true, numericality: { only_integer: true,
30
+ greater_or_equal: 0 }
31
+
32
+ scope :failed, lambda {
33
+ where(processed_at: nil).where.not(last_error: nil)
34
+ }
35
+
36
+ def to_s
37
+ "#{processor}|#{url}"
38
+ end
39
+
40
+ def process
41
+ ActiveRecord::Base.transaction do
42
+ instanciate_processor.process
43
+ self.processed_at = Time.zone.now
44
+ save!
45
+ end
46
+ end
47
+
48
+ def processed?
49
+ processed_at.present?
50
+ end
51
+
52
+ private
53
+
54
+ def instanciate_processor
55
+ processor_instancier.call(*processor_instancier_arguments)
56
+ end
57
+
58
+ def url_to_process
59
+ ::EacRubyUtils::Yaml.load(url)
60
+ end
61
+
62
+ def processor_instancier
63
+ processor.constantize.method(:new)
64
+ end
65
+
66
+ def processor_instancier_arguments
67
+ if processor_instancier_arity == 2 || processor_instancier_arity.negative?
68
+ [url_to_process, EacRubyUtils::Yaml.load(extra_data)]
69
+ elsif processor_instancier_arity == 1
70
+ [processor_instancier.call(url_to_process)]
71
+ else
72
+ raise("#{processor}.initialize should has 1 or 2 or * arguments")
73
+ end
74
+ end
75
+
76
+ def processor_instancier_arity
77
+ processor.constantize.instance_method(:initialize).arity
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/yaml'
4
+
5
+ module Aranha
6
+ class ProcessorConfiguration < ::ActiveRecord::Base
7
+ DEFAULT_TIMEOUT = 12.hours
8
+
9
+ class << self
10
+ # @return [Enumerator<String>]
11
+ def processor_class_list
12
+ ::Set.new(processor_class_list_from_addresses + processor_class_list_from_start_points)
13
+ .to_enum.sort
14
+ end
15
+
16
+ # @return [Hash<String, String>]
17
+ def processor_class_options
18
+ processor_class_list.map { |e| [e, e] }.to_h
19
+ end
20
+
21
+ private
22
+
23
+ # @return [Array<String>]
24
+ def processor_class_list_from_addresses
25
+ ::Aranha::Address.distinct.pluck(:processor)
26
+ end
27
+
28
+ # @return [Array<String>]
29
+ def processor_class_list_from_start_points
30
+ ::Aranha::StartPoint.processor_class_list.to_a
31
+ end
32
+ end
33
+
34
+ validates :processor_class, presence: true
35
+ validate :processor_class_in_list
36
+ validates :timeout_seconds, allow_blank: true,
37
+ numericality: { integer_only: true, greater_than_or_equal_to: 1 }
38
+
39
+ def processor_class_in_list
40
+ return if processor_class.blank?
41
+ return if self.class.processor_class_list.include?(processor_class)
42
+
43
+ errors.add(:processor_class, 'Not in list')
44
+ end
45
+
46
+ # @return [ActiveSupport::Duration]
47
+ def timeout
48
+ timeout_seconds.if_present(DEFAULT_TIMEOUT, &:seconds)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/yaml'
4
+
5
+ module Aranha
6
+ class StartPoint < ::ActiveRecord::Base
7
+ class << self
8
+ def add_processor_class(klass)
9
+ processor_class_list_var.add(klass.to_s)
10
+ end
11
+
12
+ def processor_class_list
13
+ processor_class_list_var.to_enum
14
+ end
15
+
16
+ def processor_class_options
17
+ processor_class_list.map { |e| [e, e] }.to_h
18
+ end
19
+
20
+ private
21
+
22
+ def processor_class_list_var
23
+ @processor_class_list_var ||= Set.new
24
+ end
25
+ end
26
+
27
+ validates :uri, presence: true, uniqueness: true,
28
+ format: { with: ::URI::DEFAULT_PARSER.make_regexp }
29
+ validates :processor_class, presence: true
30
+ validate :processor_class_in_list
31
+
32
+ def extra_data
33
+ extra_data_yaml.nil? ? nil : ::EacRubyUtils::Yaml.load(extra_data_yaml)
34
+ end
35
+
36
+ def extra_data=(value)
37
+ self.extra_data_yaml = ::EacRubyUtils::Yaml.dump(value)
38
+ end
39
+
40
+ def processor_class_in_list
41
+ return if processor_class.blank?
42
+ return if self.class.processor_class_list.include?(processor_class)
43
+
44
+ errors.add(:processor_class, 'Not in list')
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aranha/rails/manager'
4
+
5
+ ::Aranha::Manager.default = ::Aranha::Rails::Manager.instance
@@ -0,0 +1,12 @@
1
+ en:
2
+ activerecord:
3
+ models:
4
+ aranha/address:
5
+ one: Aranha address
6
+ other: Aranha addresses
7
+ aranha/processor_configuration:
8
+ one: Aranha processor configuration
9
+ other: Aranha processors configurations
10
+ aranha/start_point:
11
+ one: Aranha start point
12
+ other: Aranha start points
@@ -0,0 +1,12 @@
1
+ pt-BR:
2
+ activerecord:
3
+ models:
4
+ aranha/address:
5
+ one: Endereço Aranha
6
+ other: Endereços Aranha
7
+ aranha/processor_configuration:
8
+ one: Configuração de processador Aranha
9
+ other: Configuração de processadores Aranha
10
+ aranha/start_point:
11
+ one: Ponto de Partida Aranha
12
+ other: Pontos de Partida Aranha
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::Aranha::Rails::Engine.routes.draw do
4
+ concern :active_scaffold, ActiveScaffold::Routing::Basic.new(association: true)
5
+ resources(:addresses, concerns: :active_scaffold)
6
+ resources(:processor_configurations, concerns: :active_scaffold)
7
+ resources(:start_points, concerns: :active_scaffold)
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateAranhaAddresses < (
4
+ Rails.version < '5' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
6
+ def change
7
+ create_table :aranha_addresses do |t|
8
+ t.string :url
9
+ t.string :processor
10
+ t.timestamp :processed_at
11
+
12
+ t.timestamps null: false
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddExtraDataToAranhaAddresses < (
4
+ Rails.version < '5' ? ActiveRecord::Migration : ActiveRecord::Migration[4.2]
5
+ )
6
+ def change
7
+ add_column :aranha_addresses, :extra_data, :text
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateAranhaStartPoints < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :aranha_start_points do |t|
6
+ t.string :uri
7
+ t.string :processor_class
8
+ t.string :extra_data_yaml
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddDelayedJobToAranhaAddresses < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_reference :aranha_addresses, :delayed_job, foreign_key: false
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddTriesCountToAranhaAddresses < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column :aranha_addresses, :tries_count, :integer, null: false, default: 0
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddLastErrorToAranhaAddresses < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column :aranha_addresses, :last_error, :text
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateAranhaProcessorConfigurations < ActiveRecord::Migration[5.1]
4
+ def change
5
+ create_table :aranha_processor_configurations do |t|
6
+ t.string :processor_class
7
+ t.integer :timeout_seconds, null: true
8
+
9
+ t.timestamps null: false
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddEnabledToAranhaProcessorConfigurations < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column :aranha_processor_configurations, :enabled, :boolean, default: true, null: false
6
+ end
7
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Aranha
4
4
  module Rails
5
- VERSION = '0.7.0'
5
+ VERSION = '0.7.1'
6
6
  end
7
7
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::EacRubyUtils::Rspec.default_setup.describe_rubocop
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/rspec/default_setup'
4
+ ::EacRubyUtils::Rspec.default_setup_create(::File.expand_path('..', __dir__))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aranha-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Put here the authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-15 00:00:00.000000000 Z
11
+ date: 2021-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_scaffold
@@ -146,6 +146,32 @@ executables: []
146
146
  extensions: []
147
147
  extra_rdoc_files: []
148
148
  files:
149
+ - ".rspec"
150
+ - ".rubocop.yml"
151
+ - Gemfile
152
+ - app/assets/javascripts/aranha/application.js
153
+ - app/assets/stylesheets/aranha/application.css
154
+ - app/controllers/aranha/addresses_controller.rb
155
+ - app/controllers/aranha/processor_configurations_controller.rb
156
+ - app/controllers/aranha/start_points_controller.rb
157
+ - app/models/aranha/address.rb
158
+ - app/models/aranha/address/delayed_job.rb
159
+ - app/models/aranha/address/processor.rb
160
+ - app/models/aranha/address/scheduling.rb
161
+ - app/models/aranha/processor_configuration.rb
162
+ - app/models/aranha/start_point.rb
163
+ - config/initializers/aranha.rb
164
+ - config/locales/en.yml
165
+ - config/locales/pt-BR.yml
166
+ - config/routes.rb
167
+ - db/migrate/20171201021251_create_aranha_addresses.rb
168
+ - db/migrate/20181125042102_add_extra_data_to_aranha_addresses.rb
169
+ - db/migrate/20201128202212_create_aranha_start_points.rb
170
+ - db/migrate/20210720023620_add_delayed_job_to_aranha_addresses.rb
171
+ - db/migrate/20210721171416_add_tries_count_to_aranha_addresses.rb
172
+ - db/migrate/20210721185222_add_last_error_to_aranha_addresses.rb
173
+ - db/migrate/20210814220540_create_aranha_processor_configurations.rb
174
+ - db/migrate/20210815160543_add_enabled_to_aranha_processor_configurations.rb
149
175
  - lib/aranha/rails.rb
150
176
  - lib/aranha/rails/engine.rb
151
177
  - lib/aranha/rails/fixtures_download.rb
@@ -154,6 +180,8 @@ files:
154
180
  - lib/aranha/rails/process.rb
155
181
  - lib/aranha/rails/version.rb
156
182
  - lib/tasks/aranha.rake
183
+ - spec/rubocop_spec.rb
184
+ - spec/spec_helper.rb
157
185
  homepage:
158
186
  licenses: []
159
187
  metadata: {}
@@ -176,4 +204,9 @@ rubygems_version: 3.1.6
176
204
  signing_key:
177
205
  specification_version: 4
178
206
  summary: Put here de description.
179
- test_files: []
207
+ test_files:
208
+ - spec/rubocop_spec.rb
209
+ - spec/spec_helper.rb
210
+ - ".rspec"
211
+ - Gemfile
212
+ - ".rubocop.yml"