asyncapi-client 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +148 -0
  4. data/Rakefile +26 -0
  5. data/app/controllers/asyncapi/client/v1/jobs_controller.rb +28 -0
  6. data/app/models/asyncapi/client/callback_runner.rb +30 -0
  7. data/app/models/asyncapi/client/job.rb +95 -0
  8. data/app/services/asyncapi/client/update_job.rb +39 -0
  9. data/app/workers/asyncapi/client/cleaner_worker.rb +16 -0
  10. data/app/workers/asyncapi/client/job_cleaner_worker.rb +26 -0
  11. data/app/workers/asyncapi/client/job_post_worker.rb +50 -0
  12. data/app/workers/asyncapi/client/job_status_worker.rb +28 -0
  13. data/app/workers/asyncapi/client/job_time_out_worker.rb +25 -0
  14. data/config/routes.rb +5 -0
  15. data/db/migrate/20141104030959_create_asyncapi_client_jobs.rb +17 -0
  16. data/db/migrate/20141119011011_add_callback_params_to_asyncapi_client_jobs.rb +5 -0
  17. data/db/migrate/20141212064041_add_secret_to_asyncapi_client_job.rb +5 -0
  18. data/db/migrate/20150202062211_add_expired_at_to_asyncapi_client_job.rb +5 -0
  19. data/db/migrate/20150202062320_populate_asyncapi_client_job_expired_at.rb +7 -0
  20. data/db/migrate/20150610053320_add_on_time_out_to_asyncapi_client_job.rb +5 -0
  21. data/db/migrate/20150612082965_add_time_out_index_to_asyncapi_client_job.rb +5 -0
  22. data/lib/asyncapi-client.rb +1 -0
  23. data/lib/asyncapi/client.rb +25 -0
  24. data/lib/asyncapi/client/engine.rb +18 -0
  25. data/lib/asyncapi/client/factories.rb +2 -0
  26. data/lib/asyncapi/client/version.rb +5 -0
  27. data/lib/generators/asyncapi/client/config_generator.rb +17 -0
  28. data/spec/factories/job.rb +7 -0
  29. metadata +285 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 13ebb832003a17b09de81bdfb57189642d7fcadc
4
+ data.tar.gz: 138494b7d2eb080eaab93682140874b57b3737b6
5
+ SHA512:
6
+ metadata.gz: ea09a451882fb31a7d9c2ed01f1f111b853bf2bc61e1a513266767ea0ce9d35ab242e08168d771b3690696ac572641660b2bbaefff5ac60598d94b7aa0531bc8
7
+ data.tar.gz: ead656b31c998c890eb930133aa27f50cdc457c35b6b0ba50c115ecb4c113bdff2b5077809b53c3978ec4d87c7185f39592f5853779d62272d64443a7dff752b
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 G5Search
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # Asyncapi::Client
2
+
3
+ Asyncapi::Client is a Rails engine that easily allows asynchronous communication with a [Asyncapi::Server](https://github.com/G5/asyncapi-server)-based API server.
4
+
5
+ This avoids tying up your web servers executing long running processes. Scaling typically requires more workers.
6
+
7
+ # Usage
8
+
9
+ To communicate with the server (in the spirit of running things in the background, call the following from a worker):
10
+
11
+ ```ruby
12
+ Asyncapi::Client::Job.post(
13
+ "http://server.com/long/running/process",
14
+ # Options below are optional
15
+ body: {info: "i want to send"},
16
+ headers: { AUTHORIZATION: "Bearer XYZ" },
17
+ on_success: DoOnSuccess,
18
+ on_error: DoOnError,
19
+ on_queue: DoOnQueue,
20
+ on_time_out: DoOnTimeOut,
21
+ time_out: 2.minutes # Defaults to nil (never time out)
22
+ )
23
+ ```
24
+
25
+ *Jobs that should be timed out are marked as `timed_out` approximately every minute.*
26
+
27
+ Each of the `on_*` classes will get executed. For example, when the job is queued on the server, `DoOnQueue#call` will get called with the `Asyncapi::Client::Job` instance passed in. Example:
28
+
29
+ ```ruby
30
+ class DoOnQueue < Asyncapi::Client::CallbackRunner
31
+ def call
32
+ # you have access to: job, callback_params
33
+ Rails.logger.info "Job##{job.id} successfully queued with body: #{job.body}"
34
+ end
35
+ end
36
+
37
+ class DoOnSuccess < Asyncapi::Client::CallbackRunner
38
+ def self.call
39
+ Rails.logger.info "Job##{job.id} is done. The server's response: #{job.message}"
40
+ end
41
+ end
42
+
43
+ class DoOnError < Asyncapi::Client::CallbackRunner
44
+ def call
45
+ # you have access to: job and it fields: callback_params, :body, :headers, :message
46
+ Rails.logger.info "Job##{job.id} failed. The server's response: #{job.message}"
47
+ end
48
+ end
49
+ ```
50
+
51
+ In the callback classes, you have access to the `job` and its fields (directly):
52
+
53
+ - `callback_params`
54
+ - `body`
55
+ - `headers`
56
+ - `message`
57
+
58
+ Currently, this Engine only works with [Sidekiq](http://sidekiq.org), [typhoeus](https://github.com/typhoeus/typhoeus), and [kaminari](https://github.com/amatsuda/kaminari). Customizing these can be introduced as needed.
59
+
60
+ To run the application, you need to have the Sidekiq workers running as well.
61
+
62
+ There is a feed of all jobs that can be accessed via `/asyncapi/client/v1/jobs.json`. You can pass `per_page` and `page` to paginate through the records. Pagination is done by [api-pagination](https://github.com/davidcelis/api-pagination) via kaminari.
63
+
64
+ ## Expiry
65
+
66
+ To make space in the database, old jobs must be deleted. By default, jobs older than 10 days will be deleted in both the Asyncapi Client and Asyncapi Server. Asyncapi Client is responsible for deleting the jobs it no longer needs a response from on the server.
67
+
68
+ By default, jobs 10 days old and older will be deleted. You can change this setting by putting this in an initializer:
69
+
70
+ ```ruby
71
+ Asyncapi::Client.expiry_threshold = 5.days
72
+ ```
73
+
74
+ If you don't ever want the jobs to get delete, set the threshold to `nil`.
75
+
76
+ # Installation
77
+
78
+ **Note**: if you're using the `protected_attributes`, also see the "Optional" section below.
79
+
80
+ ## Required
81
+
82
+ Add the gem to the Gemfile:
83
+
84
+ ```
85
+ gem "asyncapi-client"
86
+ ```
87
+
88
+ From your Rails app:
89
+
90
+ ```
91
+ rails g asyncapi:client:config
92
+ rake asyncapi_client:install:migrations
93
+ rake db:migrate
94
+ ```
95
+
96
+ Make sure you have `:host` in the `default_url_options` set up for your server. Example `config/initializers/default_url_options.rb`:
97
+
98
+ ```ruby
99
+ Rails.application.routes.default_url_options ||= {}
100
+ Rails.application.routes.default_url_options[:host] = ENV["HOST"]
101
+ ```
102
+
103
+ ## Optional:
104
+
105
+ If you want to change the controller that the engine's controllers inherit from, from an initializer:
106
+
107
+ ```
108
+ Asyncapi::Client.configure do |c|
109
+ c.parent_controller = Api::BaseController
110
+ end
111
+ ```
112
+
113
+ If you use `protected_attributes`, you need to whitelist attributes. In an initializer:
114
+
115
+ ```ruby
116
+ Asyncapi::Client::Job.attr_accessible(
117
+ :follow_up_at,
118
+ :time_out_at,
119
+ :on_queue,
120
+ :on_success,
121
+ :on_error,
122
+ :headers,
123
+ :body,
124
+ :status,
125
+ )
126
+ ```
127
+
128
+ If you use FactoryGirl, you can require the factories for easy testing and stubbing:
129
+
130
+ ```ruby
131
+ require "asyncapi/client/factories"
132
+ ```
133
+
134
+ ## Security
135
+
136
+ `asyncapi-client` generates a secret for the job using `SecureRandom.uuid`, and sends this to the app using `asyncapi-server`. The server app, using the latest compatible gem, will reply with the secret in the params. `asyncapi-client` will make sure the job id matches with the given secret.
137
+
138
+ ## License
139
+
140
+ Copyright (c) 2014 G5
141
+
142
+ MIT License
143
+
144
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
145
+
146
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
147
+
148
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'AsyncapiClient'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rspec/core/rake_task'
25
+ task :default => :spec
26
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,28 @@
1
+ module Asyncapi::Client
2
+ module V1
3
+ class JobsController < Asyncapi::Client.parent_controller
4
+ respond_to :json
5
+
6
+ def index
7
+ jobs = Job.all
8
+ paginate json: jobs
9
+ end
10
+
11
+ def update
12
+ if job = Job.find_by(id: params[:id], secret: params[:job][:secret])
13
+ UpdateJob.execute(job: job, params: job_params)
14
+ respond_with job
15
+ else
16
+ render nothing: true, status: 403
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def job_params
23
+ params.require(:job).permit(:status, :message)
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ module Asyncapi::Client
2
+ class CallbackRunner
3
+
4
+ attr_accessor :job_id
5
+ DELEGATED_ATTRS = [
6
+ :callback_params,
7
+ :body,
8
+ :headers,
9
+ :message,
10
+ ]
11
+ delegate *DELEGATED_ATTRS, to: :job
12
+
13
+ def self.call(job_id)
14
+ self.new(job_id).call
15
+ end
16
+
17
+ def initialize(job_id)
18
+ self.job_id = job_id
19
+ end
20
+
21
+ def call
22
+ fail StandardError, "over-ride me"
23
+ end
24
+
25
+ def job
26
+ @job ||= Job.find(job_id)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,95 @@
1
+ module Asyncapi::Client
2
+ class Job < ActiveRecord::Base
3
+
4
+ after_initialize :generate_secret
5
+ before_create :set_expired_at
6
+
7
+ enum status: %i[queued success error timed_out fresh]
8
+ serialize :headers, Hash
9
+ serialize :callback_params, Hash
10
+
11
+ include AASM
12
+ aasm column: :status, enum: true do
13
+ state :fresh, initial: true
14
+ state :queued
15
+ state :success
16
+ state :error
17
+ state :timed_out
18
+
19
+ event :enqueue do
20
+ transitions from: :fresh, to: :queued
21
+ end
22
+
23
+ event :succeed do
24
+ transitions from: :queued, to: :success
25
+ end
26
+
27
+ event :fail do
28
+ transitions from: :queued, to: :error
29
+ end
30
+
31
+ event :time_out do
32
+ transitions from: [:fresh, :queued], to: :timed_out
33
+ end
34
+ end
35
+
36
+ scope :expired, -> { where(arel_table[:expired_at].lt(Time.now)) }
37
+ scope :with_time_out, -> { where(arel_table[:time_out_at].not_eq(nil)) }
38
+ scope :for_time_out, -> do
39
+ with_time_out.where(arel_table[:time_out_at].lt(Time.now))
40
+ end
41
+
42
+ def self.post(url,
43
+ headers: nil,
44
+ body: nil,
45
+ on_queue: nil,
46
+ on_success: nil,
47
+ on_error: nil,
48
+ on_time_out: nil,
49
+ callback_params: {},
50
+ follow_up: 5.minutes,
51
+ time_out: nil)
52
+
53
+ args = {
54
+ follow_up_at: follow_up.from_now,
55
+ on_queue: on_queue,
56
+ on_success: on_success,
57
+ on_error: on_error,
58
+ on_time_out: on_time_out,
59
+ callback_params: callback_params,
60
+ headers: headers,
61
+ body: body,
62
+ }
63
+ args[:time_out_at] = time_out.from_now if time_out
64
+ job = create(args)
65
+ JobPostWorker.perform_async(job.id, url)
66
+ CleanerWorker.perform_async
67
+ end
68
+
69
+ def url
70
+ Asyncapi::Client::Engine.routes.url_helpers.v1_job_url(self)
71
+ end
72
+
73
+ def body=(body)
74
+ json = body.is_a?(Hash) ? body.to_json : body
75
+ write_attribute :body, json
76
+ end
77
+
78
+ [:on_success, :on_error, :on_queue, :on_time_out].each do |attr|
79
+ define_method("#{attr}=") do |klass|
80
+ write_attribute attr, klass.to_s
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def set_expired_at
87
+ self.expired_at ||= Asyncapi::Client.expiry_threshold.from_now
88
+ end
89
+
90
+ def generate_secret
91
+ self.secret ||= SecureRandom.uuid
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,39 @@
1
+ module Asyncapi::Client
2
+ class UpdateJob
3
+
4
+ def self.execute(job: job, params: params)
5
+ sanitized_params = params.reject { |key, value| key.to_sym == :status }
6
+ job.assign_attributes(sanitized_params)
7
+ status = params[:status]
8
+
9
+ if may_transition?(job, to: status)
10
+ transition(job, to: status)
11
+ if job.status_changed? && job.save
12
+ JobStatusWorker.perform_async(job.id)
13
+ else
14
+ job.save
15
+ end
16
+ elsif !may_transition?(job, to: status) && job.status == status
17
+ job.save
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def self.event_for(status)
24
+ case status
25
+ when "success"; :succeed
26
+ when "error"; :fail
27
+ end
28
+ end
29
+
30
+ def self.may_transition?(job, to:)
31
+ job.send(:"may_#{event_for(to)}?")
32
+ end
33
+
34
+ def self.transition(job, to:)
35
+ job.send(event_for(to)) if may_transition?(job, to: to)
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module Asyncapi
2
+ module Client
3
+ class CleanerWorker
4
+
5
+ include Sidekiq::Worker
6
+ sidekiq_options retry: false
7
+
8
+ def perform
9
+ Job.expired.find_each do |job|
10
+ JobCleanerWorker.perform_async(job.id)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ module Asyncapi
2
+ module Client
3
+ class JobCleanerWorker
4
+
5
+ include Sidekiq::Worker
6
+ sidekiq_options retry: false
7
+
8
+ def perform(job_id)
9
+ if job = Job.find_by(id: job_id)
10
+ destroy_remote job
11
+ job.destroy
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def destroy_remote(job)
18
+ Typhoeus.delete(job.server_job_url, {
19
+ params: { secret: job.secret },
20
+ headers: job.headers,
21
+ })
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ module Asyncapi::Client
2
+ class JobPostWorker
3
+
4
+ include Sidekiq::Worker
5
+ sidekiq_options retry: false
6
+
7
+ def perform(job_id, server_url)
8
+ job = Job.find(job_id)
9
+ server_params = server_params_from(job, job.body)
10
+ response = Typhoeus.post(server_url, {
11
+ body: server_params,
12
+ headers: job.headers,
13
+ })
14
+ process response, job
15
+ end
16
+
17
+ private
18
+
19
+ def process(response, job)
20
+ if response.success?
21
+ job.assign_attributes(job_params_from(response))
22
+ job.enqueue
23
+ if job.save!
24
+ JobStatusWorker.perform_async(job.id)
25
+ end
26
+ else
27
+ if job.update_attributes(status: :error, message: response.body)
28
+ JobStatusWorker.perform_async(job.id)
29
+ end
30
+ end
31
+ end
32
+
33
+ def job_params_from(response)
34
+ response_body = JSON.parse(response.body).with_indifferent_access
35
+ server_job_params = response_body[:job]
36
+ {server_job_url: server_job_params[:url]}
37
+ end
38
+
39
+ def server_params_from(job, params)
40
+ {
41
+ job: {
42
+ callback_url: job.url,
43
+ params: params,
44
+ secret: job.secret,
45
+ }
46
+ }
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ module Asyncapi::Client
2
+ class JobStatusWorker
3
+
4
+ include Sidekiq::Worker
5
+ sidekiq_options retry: false
6
+
7
+ STATUS_CALLBACK_MAP = {
8
+ queued: :on_queue,
9
+ success: :on_success,
10
+ error: :on_error,
11
+ timed_out: :on_time_out,
12
+ }.with_indifferent_access
13
+
14
+ def perform(job_id)
15
+ job = Job.find(job_id)
16
+ callback_method = STATUS_CALLBACK_MAP[job.status]
17
+ return unless job.respond_to?(callback_method)
18
+ class_name = job.send(callback_method)
19
+ begin
20
+ callback_class = class_name.constantize
21
+ rescue NameError
22
+ return
23
+ end
24
+ callback_class.call(job.id)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module Asyncapi::Client
2
+ class JobTimeOutWorker
3
+
4
+ include Sidekiq::Worker
5
+ include Sidetiq::Schedulable
6
+
7
+ sidekiq_options retry: false
8
+
9
+ recurrence { minutely }
10
+
11
+ def perform
12
+ Job.for_time_out.find_each do |job|
13
+ time_out_job(job) if job.may_time_out?
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def time_out_job(job)
20
+ job.update_attributes(status: :timed_out)
21
+ JobStatusWorker.perform_async(job.id)
22
+ end
23
+
24
+ end
25
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ Asyncapi::Client::Engine.routes.draw do
2
+ namespace :v1 do
3
+ resources :jobs
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ class CreateAsyncapiClientJobs < ActiveRecord::Migration
2
+ def change
3
+ create_table :asyncapi_client_jobs do |t|
4
+ t.string "server_job_url"
5
+ t.integer "status"
6
+ t.text "message"
7
+ t.datetime "follow_up_at"
8
+ t.datetime "time_out_at"
9
+ t.string "on_queue"
10
+ t.string "on_success"
11
+ t.string "on_error"
12
+ t.text "body"
13
+ t.text "headers"
14
+ t.timestamps
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ class AddCallbackParamsToAsyncapiClientJobs < ActiveRecord::Migration
2
+ def change
3
+ add_column :asyncapi_client_jobs, :callback_params, :text
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddSecretToAsyncapiClientJob < ActiveRecord::Migration
2
+ def change
3
+ add_column :asyncapi_client_jobs, :secret, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddExpiredAtToAsyncapiClientJob < ActiveRecord::Migration
2
+ def change
3
+ add_column :asyncapi_client_jobs, :expired_at, :datetime
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class PopulateAsyncapiClientJobExpiredAt < ActiveRecord::Migration
2
+ def change
3
+ Asyncapi::Client::Job.find_each do |job|
4
+ job.update_attributes(expired_at: Asyncapi::Client.expiry_threshold.from_now)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ class AddOnTimeOutToAsyncapiClientJob < ActiveRecord::Migration
2
+ def change
3
+ add_column :asyncapi_client_jobs, :on_time_out, :string
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddTimeOutIndexToAsyncapiClientJob < ActiveRecord::Migration
2
+ def change
3
+ add_index :asyncapi_client_jobs, :time_out_at
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require "asyncapi/client"
@@ -0,0 +1,25 @@
1
+ require "sidekiq"
2
+ require "sidetiq"
3
+ require "api-pagination"
4
+ require "typhoeus"
5
+ require 'aasm'
6
+ require "asyncapi/client/engine"
7
+ require "securerandom"
8
+
9
+ module Asyncapi
10
+ module Client
11
+
12
+ CONFIG_ATTRS = [:parent_controller, :expiry_threshold]
13
+ mattr_accessor(*CONFIG_ATTRS)
14
+ self.expiry_threshold = 10.days
15
+
16
+ def self.configure
17
+ yield self
18
+ end
19
+
20
+ def self.parent_controller
21
+ @@parent_controller || ActionController::Base
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module Asyncapi
2
+ module Client
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace Asyncapi::Client
5
+ engine_name "asyncapi_client"
6
+
7
+ config.to_prepare do
8
+ Dir.glob(Engine.root + "app/workers/**/*.rb").each do |c|
9
+ require_dependency(c)
10
+ end
11
+
12
+ Engine.routes.default_url_options =
13
+ Rails.application.routes.default_url_options
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ factories_dir = File.expand_path("../../../../spec/factories/*.rb", __FILE__)
2
+ Dir[factories_dir].each { |f| require f }
@@ -0,0 +1,5 @@
1
+ module Asyncapi
2
+ module Client
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ require "asyncapi/client/engine"
2
+
3
+ module Asyncapi::Client
4
+ class ConfigGenerator < Rails::Generators::Base
5
+
6
+ desc "Inserts routes code for Asyncapi::Client"
7
+
8
+ def mount_on_routes
9
+ inject_into_file(
10
+ "config/routes.rb",
11
+ %Q( mount Asyncapi::Client::Engine, at: "/asyncapi/client"\n),
12
+ before: /^end/
13
+ )
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+
3
+ factory :asyncapi_client_job, class: Asyncapi::Client::Job do
4
+
5
+ end
6
+
7
+ end
metadata ADDED
@@ -0,0 +1,285 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: asyncapi-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - G5
8
+ - Marc Ignacio
9
+ - Ramon Tayag
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2015-06-29 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: 4.1.5
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: 4.1.5
29
+ - !ruby/object:Gem::Dependency
30
+ name: sidekiq
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: sidetiq
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: kaminari
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: api-pagination
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: typhoeus
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: aasm
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '4.0'
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '4.0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: sqlite3
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: rspec-rails
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ - !ruby/object:Gem::Dependency
142
+ name: rspec-its
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ type: :development
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ - !ruby/object:Gem::Dependency
156
+ name: pry
157
+ requirement: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ type: :development
163
+ prerelease: false
164
+ version_requirements: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ - !ruby/object:Gem::Dependency
170
+ name: factory_girl
171
+ requirement: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ type: :development
177
+ prerelease: false
178
+ version_requirements: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ - !ruby/object:Gem::Dependency
184
+ name: database_cleaner
185
+ requirement: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ type: :development
191
+ prerelease: false
192
+ version_requirements: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ - !ruby/object:Gem::Dependency
198
+ name: rspec-sidekiq
199
+ requirement: !ruby/object:Gem::Requirement
200
+ requirements:
201
+ - - ">="
202
+ - !ruby/object:Gem::Version
203
+ version: '0'
204
+ type: :development
205
+ prerelease: false
206
+ version_requirements: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '0'
211
+ - !ruby/object:Gem::Dependency
212
+ name: timecop
213
+ requirement: !ruby/object:Gem::Requirement
214
+ requirements:
215
+ - - ">="
216
+ - !ruby/object:Gem::Version
217
+ version: '0'
218
+ type: :development
219
+ prerelease: false
220
+ version_requirements: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - ">="
223
+ - !ruby/object:Gem::Version
224
+ version: '0'
225
+ description: Asynchronous API communication
226
+ email:
227
+ - lateam@getg5.com
228
+ - marcrendlignacio@gmail.com
229
+ - ramon.tayag@gmail.com
230
+ executables: []
231
+ extensions: []
232
+ extra_rdoc_files: []
233
+ files:
234
+ - MIT-LICENSE
235
+ - README.md
236
+ - Rakefile
237
+ - app/controllers/asyncapi/client/v1/jobs_controller.rb
238
+ - app/models/asyncapi/client/callback_runner.rb
239
+ - app/models/asyncapi/client/job.rb
240
+ - app/services/asyncapi/client/update_job.rb
241
+ - app/workers/asyncapi/client/cleaner_worker.rb
242
+ - app/workers/asyncapi/client/job_cleaner_worker.rb
243
+ - app/workers/asyncapi/client/job_post_worker.rb
244
+ - app/workers/asyncapi/client/job_status_worker.rb
245
+ - app/workers/asyncapi/client/job_time_out_worker.rb
246
+ - config/routes.rb
247
+ - db/migrate/20141104030959_create_asyncapi_client_jobs.rb
248
+ - db/migrate/20141119011011_add_callback_params_to_asyncapi_client_jobs.rb
249
+ - db/migrate/20141212064041_add_secret_to_asyncapi_client_job.rb
250
+ - db/migrate/20150202062211_add_expired_at_to_asyncapi_client_job.rb
251
+ - db/migrate/20150202062320_populate_asyncapi_client_job_expired_at.rb
252
+ - db/migrate/20150610053320_add_on_time_out_to_asyncapi_client_job.rb
253
+ - db/migrate/20150612082965_add_time_out_index_to_asyncapi_client_job.rb
254
+ - lib/asyncapi-client.rb
255
+ - lib/asyncapi/client.rb
256
+ - lib/asyncapi/client/engine.rb
257
+ - lib/asyncapi/client/factories.rb
258
+ - lib/asyncapi/client/version.rb
259
+ - lib/generators/asyncapi/client/config_generator.rb
260
+ - spec/factories/job.rb
261
+ homepage: https://github.com/G5/asyncapi-client
262
+ licenses:
263
+ - MIT
264
+ metadata: {}
265
+ post_install_message:
266
+ rdoc_options: []
267
+ require_paths:
268
+ - lib
269
+ required_ruby_version: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - ">="
272
+ - !ruby/object:Gem::Version
273
+ version: '0'
274
+ required_rubygems_version: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - ">="
277
+ - !ruby/object:Gem::Version
278
+ version: '0'
279
+ requirements: []
280
+ rubyforge_project:
281
+ rubygems_version: 2.4.5
282
+ signing_key:
283
+ specification_version: 4
284
+ summary: Asynchronous API communication
285
+ test_files: []