startback-jobs 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 485b5ef6145820975b98f3f457c276c7b3fd824a0b63752e4688110c9935b642
4
+ data.tar.gz: 5cbadc773d07ea6108488e86a58d3cc9ce1e919fa23359ac87f340e94235610c
5
+ SHA512:
6
+ metadata.gz: dddbd22a80647d96483a2e674a0e306e7414fb7cb445474571db569e8aff89e88178dbab5e5de5b29eaf4ce925f54b22df988d88d9e41c5e1fff96fe0a7cb796
7
+ data.tar.gz: 10de6fca4203d5e2ef706967545d3e24460c4593382a47b58e9fae2eeb240dce9ec19b213469e8a6ad05d87552e9aed5ee3314bcf6de4a453c330fd603f4742e
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ gem 'startback', path: '../..'
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ def shell(*cmds)
4
+ cmd = cmds.join("\n")
5
+ puts cmd
6
+ system cmd
7
+ end
8
+
9
+ #
10
+ # Install all tasks found in tasks folder
11
+ #
12
+ # See .rake files there for complete documentation.
13
+ #
14
+ Dir["tasks/*.rake"].each do |taskfile|
15
+ load taskfile
16
+ end
17
+
18
+ task :default => :test
@@ -0,0 +1,17 @@
1
+ module Startback
2
+ module Support
3
+ module OperationRunner
4
+
5
+ def run_as_job(op)
6
+ run Startback::Jobs::CreateJob.new({
7
+ isReady: false,
8
+ opClass: op.class.name,
9
+ opInput: op.input,
10
+ opContext: context.to_h,
11
+ createdBy: '',
12
+ })
13
+ end
14
+
15
+ end # module OperationRunner
16
+ end # module Support
17
+ end # module Startback
@@ -0,0 +1,12 @@
1
+ module Startback
2
+ module Web
3
+ class Api
4
+
5
+ def serve_job(job)
6
+ job.result.api_serve(self)
7
+ end
8
+ protected :serve_job
9
+
10
+ end # class Api
11
+ end # module Web
12
+ end # module Startback
@@ -0,0 +1,2 @@
1
+ require_relative 'ext/web/api'
2
+ require_relative 'ext/support/operation_runner'
@@ -0,0 +1,15 @@
1
+ module Startback
2
+ module Jobs
3
+ class Agent < Startback::Event::Agent
4
+
5
+ def install_listeners
6
+ async Event::JobCreated, 'job-runner'
7
+ end
8
+
9
+ def call(event)
10
+ run RunJob.new(event.data.to_h)
11
+ end
12
+
13
+ end # class Agent
14
+ end # module Jobs
15
+ end # module Startback
@@ -0,0 +1,12 @@
1
+ module Startback
2
+ module Jobs
3
+ class Api < Startback::Web::Api
4
+
5
+ get %r{/([^\/]+)/result/?} do |id|
6
+ job = context.factor(Services).get_job!(id: id)
7
+ Support::JobResult.for(job).api_serve(self)
8
+ end
9
+
10
+ end # class Api
11
+ end # module Jobs
12
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ module Jobs
3
+ class Event
4
+ class JobCreated < Event
5
+ end # class JobCreated
6
+ end # class Event
7
+ end # module Jobs
8
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ module Jobs
3
+ class Event
4
+ class JobRan < Event
5
+ end # class JobRan
6
+ end # class Event
7
+ end # module Jobs
8
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ module Jobs
3
+ class Event < Startback::Event
4
+ end # class Event
5
+ end # module Jobs
6
+ end # module Startback
7
+ require_relative 'event/job_created'
8
+ require_relative 'event/job_ran'
@@ -0,0 +1,35 @@
1
+ module Startback
2
+ module Jobs
3
+ class Model
4
+ class Job < Model
5
+ def self.ref(data)
6
+ dress(data, 'Job.Ref')
7
+ end
8
+
9
+ def self.full(data)
10
+ dress(data, 'Job.Full')
11
+ end
12
+
13
+ def ready?
14
+ self.isReady
15
+ end
16
+
17
+ def not_ready?
18
+ !ready?
19
+ end
20
+
21
+ def expired?
22
+ self.expiredAt && self.expiredAt < Time.now
23
+ end
24
+
25
+ def fully_consumed?
26
+ self.consumedMax && (self.consumedCount || 0 >= self.consumedMax)
27
+ end
28
+
29
+ def result
30
+ Support::JobResult.for(self)
31
+ end
32
+ end # class Job
33
+ end # class Model
34
+ end # module Jobs
35
+ end # module Startback
@@ -0,0 +1,12 @@
1
+ module Startback
2
+ module Jobs
3
+ class Model < Startback::Model
4
+
5
+ def self.dress(data, schema)
6
+ new(System[schema].dress(data))
7
+ end
8
+
9
+ end # class Model
10
+ end # module Jobs
11
+ end # module Startback
12
+ require_relative 'model/job'
@@ -0,0 +1,37 @@
1
+ module Startback
2
+ module Jobs
3
+ class CreateJob < Operation
4
+
5
+ def initialize(input)
6
+ super(System['Job.CreationRequest'].dress(input))
7
+ end
8
+
9
+ def call
10
+ @job = Model::Job.full({
11
+ id: SecureRandom.urlsafe_base64(16),
12
+ opInput: {},
13
+ opContext: {},
14
+ opResult: nil,
15
+ strategy: 'NotReady',
16
+ strategyOptions: {},
17
+ expiresAt: nil,
18
+ refreshFreq: nil,
19
+ refreshedAt: nil,
20
+ consumeMax: nil,
21
+ consumeCount: 0,
22
+ createdAt: Time.now,
23
+ createdBy: nil,
24
+ }.merge(input))
25
+
26
+ context.world.startback_jobs.insert(@job.to_data)
27
+
28
+ @job
29
+ end
30
+
31
+ emits(Event::JobCreated) do
32
+ { id: @job.id }
33
+ end
34
+
35
+ end # class CreateJob
36
+ end # module Jobs
37
+ end # module Startback
@@ -0,0 +1,35 @@
1
+ module Startback
2
+ module Jobs
3
+ class RunJob < Operation
4
+
5
+ def initialize(input)
6
+ super(System['Job.Ref'].dress(input))
7
+ end
8
+
9
+ def call
10
+ services = context.factor(Services)
11
+ @job = services.get_job!(input)
12
+
13
+ job_context = context.fork(@job.op_context)
14
+ job_class = ::Kernel.const_get(@job.op_class)
15
+ job_input = @job.op_input
16
+
17
+ op_result = with_context(job_context) do
18
+ run job_class.new(job_input)
19
+ end
20
+
21
+ services.update_job!(input, {
22
+ opResult: op_result,
23
+ isReady: true,
24
+ })
25
+
26
+ op_result
27
+ end
28
+
29
+ emits(Event::JobRan) do
30
+ { id: @job.id }
31
+ end
32
+
33
+ end # class RunJob
34
+ end # module Jobs
35
+ end # module Startback
@@ -0,0 +1,8 @@
1
+ module Startback
2
+ module Jobs
3
+ class Operation < Startback::Operation
4
+ end # class Operation
5
+ end # module Jobs
6
+ end # module Startback
7
+ require_relative 'operation/create_job'
8
+ require_relative 'operation/run_job'
@@ -0,0 +1,25 @@
1
+ module Startback
2
+ module Jobs
3
+ class Services < Startback::Services
4
+
5
+ def get_job!(ref)
6
+ job_relvar = startback_jobs.restrict(ref)
7
+ Model::Job.full(job_relvar.one)
8
+ rescue Bmg::OneError
9
+ not_found_error!("Job #{ref[:id]}")
10
+ end
11
+
12
+ def update_job!(ref, update)
13
+ job_relvar = startback_jobs.restrict(ref)
14
+ job_relvar.update(update)
15
+ end
16
+
17
+ private
18
+
19
+ def startback_jobs
20
+ context.world.startback_jobs
21
+ end
22
+
23
+ end # class Services
24
+ end # module Jobs
25
+ end # module Startback
@@ -0,0 +1,15 @@
1
+ module Startback
2
+ module Jobs
3
+ module Support
4
+ class JobResult
5
+ class Embedded < JobResult
6
+
7
+ def api_serve(api)
8
+ [200, {}, [job.opResult]]
9
+ end
10
+
11
+ end # class Embedded
12
+ end # class JobResult
13
+ end # module Support
14
+ end # module Jobs
15
+ end # module Startback
@@ -0,0 +1,15 @@
1
+ module Startback
2
+ module Jobs
3
+ module Support
4
+ class JobResult
5
+ class NotReady < JobResult
6
+
7
+ def api_serve(api)
8
+ [202, {}, []]
9
+ end
10
+
11
+ end # class NotReady
12
+ end # class JobResult
13
+ end # module Support
14
+ end # module Jobs
15
+ end # module Startback
@@ -0,0 +1,32 @@
1
+ module Startback
2
+ module Jobs
3
+ module Support
4
+ class JobResult
5
+ class Redirect < JobResult
6
+
7
+ DEFAULT_REDIRECT_OPTIONS = {
8
+ status: 301,
9
+ headers: {}
10
+ }.freeze
11
+
12
+ def api_serve(api)
13
+ options = redirect_options
14
+ [
15
+ options.status || 301,
16
+ options.headers.merge("Location" => job.opResult),
17
+ []
18
+ ]
19
+ end
20
+
21
+ def redirect_options
22
+ opts = DEFAULT_REDIRECT_OPTIONS.merge(
23
+ job.strategy_options
24
+ )
25
+ Startback::Model.new(opts)
26
+ end
27
+
28
+ end # class Embedded
29
+ end # class JobResult
30
+ end # module Support
31
+ end # module Jobs
32
+ end # module Startback
@@ -0,0 +1,31 @@
1
+ module Startback
2
+ module Jobs
3
+ module Support
4
+ class JobResult
5
+
6
+ def initialize(job)
7
+ @job = job
8
+ end
9
+ private :initialize
10
+
11
+ attr_reader :job
12
+
13
+ def self.for(job)
14
+ unless job.is_ready?
15
+ JobResult::NotReady.new(job)
16
+ else
17
+ JobResult.const_get(job.strategy).new(job)
18
+ end
19
+ end
20
+
21
+ def api_serve(api)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ end # class JobResult
26
+ end # module Support
27
+ end # module Jobs
28
+ end # module Startback
29
+ require_relative 'job_result/not_ready'
30
+ require_relative 'job_result/embedded'
31
+ require_relative 'job_result/redirect'
@@ -0,0 +1 @@
1
+ require_relative 'support/job_result'
@@ -0,0 +1,44 @@
1
+ @import finitio/data
2
+
3
+ ClassName = String
4
+
5
+ DumpableHash = { ...: .Object }
6
+
7
+ Job.Ref = {
8
+ id : String
9
+ }
10
+
11
+ Job.Strategy = String(s | %w{Embedded NotReady Redirect}.include? s )
12
+
13
+ Job.Full = {
14
+ id : String
15
+ opClass : ClassName
16
+ opInput : DumpableHash
17
+ opContext : DumpableHash
18
+ opResult : .
19
+ isReady : Boolean
20
+ strategy : Job.Strategy
21
+ strategyOptions : DumpableHash
22
+ expiresAt : DateTime|Time|Nil
23
+ refreshFreq : String|Nil
24
+ refreshedAt : DateTime|Time|Nil
25
+ consumeMax : Integer|Nil
26
+ consumeCount : Integer|Nil
27
+ createdAt : DateTime|Time|Nil
28
+ createdBy : String|Nil
29
+ }
30
+
31
+ Job.CreationRequest = {
32
+ opClass : ClassName
33
+ opInput : DumpableHash
34
+ opContext : DumpableHash
35
+ createdBy : String
36
+
37
+ isReady : Boolean
38
+ strategy :? Job.Strategy
39
+ strategyOptions :? DumpableHash
40
+
41
+ expiresAt :? DateTime|Time
42
+ refreshFreq :? String
43
+ consumeMax :? Integer
44
+ }
@@ -0,0 +1,23 @@
1
+ require 'path'
2
+ require 'finitio'
3
+ require 'startback'
4
+ require 'startback/event'
5
+ require 'startback/web/api'
6
+
7
+ module Startback
8
+ module Jobs
9
+ require_relative 'jobs/support'
10
+ require_relative 'jobs/model'
11
+ require_relative 'jobs/event'
12
+ require_relative 'jobs/operation'
13
+ require_relative 'jobs/services'
14
+ require_relative 'jobs/api'
15
+ require_relative 'jobs/agent'
16
+
17
+ require_relative './ext'
18
+
19
+ Finitio.stdlib_path(Path.dir.parent)
20
+
21
+ System = Finitio.system(Path.dir/'jobs.fio')
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'startback'
3
+ require 'startback/jobs'
4
+ require 'rack/test'
5
+ require 'bmg'
6
+
7
+ module SpecHelpers
8
+ end
9
+
10
+ RSpec.configure do |c|
11
+ c.include SpecHelpers
12
+
13
+ def a_job_data(override = {})
14
+ {
15
+ id: 'abcdef',
16
+ isReady: false,
17
+ opClass: 'CowSay',
18
+ opInput: { 'message' => 'Hello !!' },
19
+ opContext: {},
20
+ opResult: nil,
21
+ strategy: 'NotReady',
22
+ strategyOptions: {},
23
+ expiresAt: nil,
24
+ refreshFreq: nil,
25
+ refreshedAt: nil,
26
+ consumeMax: nil,
27
+ consumeCount: 0,
28
+ createdAt: DateTime.now,
29
+ createdBy: 'blambeau',
30
+ }.merge(override)
31
+ end
32
+ end
33
+
34
+ class CowSay < Startback::Operation
35
+ def initialize(input)
36
+ @input = Startback::Model.new(input)
37
+ end
38
+
39
+ def call
40
+ input.message
41
+ end
42
+ end
@@ -0,0 +1,121 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Jobs
5
+ describe Api, "GET /{id}/result/" do
6
+ include Rack::Test::Methods
7
+
8
+ let(:job_data) do
9
+ a_job_data(override)
10
+ end
11
+
12
+ let(:jobs_relvar) do
13
+ Bmg.mutable([job_data])
14
+ end
15
+
16
+ let(:context) do
17
+ Context.new.with_world(startback_jobs: jobs_relvar)
18
+ end
19
+
20
+ let(:app) do
21
+ context = self.context
22
+ Rack::Builder.new do
23
+ use Context::Middleware, context
24
+ run Jobs::Api
25
+ end
26
+ end
27
+
28
+ let(:job_id) do
29
+ 'abcdef'
30
+ end
31
+
32
+ subject do
33
+ get "/#{job_id}/result/"
34
+ end
35
+
36
+ context 'when the job does not exist' do
37
+ let(:job_id) do
38
+ "no-such-one"
39
+ end
40
+
41
+ let(:override) do
42
+ {}
43
+ end
44
+
45
+ it 'raises' do
46
+ expect{
47
+ subject
48
+ }.to raise_error(Startback::Errors::NotFoundError)
49
+ end
50
+ end
51
+
52
+ context 'when the job is not ready yet' do
53
+ let(:override) do
54
+ {
55
+ isReady: false,
56
+ strategy: 'NotReady',
57
+ }
58
+ end
59
+
60
+ it 'works fine' do
61
+ res = subject
62
+ expect(res.status).to eql(202)
63
+ expect(res.body).to be_empty
64
+ end
65
+ end
66
+
67
+ context 'when the job is ready' do
68
+ let(:override) do
69
+ {
70
+ isReady: true,
71
+ opResult: 'Hello!!',
72
+ strategy: 'Embedded'
73
+ }
74
+ end
75
+
76
+ it 'works fine' do
77
+ res = subject
78
+ expect(res.status).to eql(200)
79
+ expect(res.body).to eql("Hello!!")
80
+ end
81
+ end
82
+
83
+ context 'when the job is ready and has to redirect' do
84
+ let(:override) do
85
+ {
86
+ isReady: true,
87
+ strategy: 'Redirect',
88
+ opResult: 'http://google.com',
89
+ }
90
+ end
91
+
92
+ it 'works fine' do
93
+ res = subject
94
+ expect(res.status).to eql(301)
95
+ expect(res['Location']).to eql("http://google.com")
96
+ end
97
+ end
98
+
99
+ context 'when the job is ready and has to redirect with a 302' do
100
+ let(:override) do
101
+ {
102
+ isReady: true,
103
+ strategy: 'Redirect',
104
+ strategyOptions: {
105
+ 'status' => 302,
106
+ 'headers' => { 'X-Mine' => 'foo' }
107
+ },
108
+ opResult: 'http://google.com',
109
+ }
110
+ end
111
+
112
+ it 'works fine' do
113
+ res = subject
114
+ expect(res.status).to eql(302)
115
+ expect(res['X-Mine']).to eql('foo')
116
+ expect(res['Location']).to eql("http://google.com")
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Jobs
5
+ class Model
6
+ describe Job do
7
+ it 'makes it easy to create an instance' do
8
+ job = Job.new(a_job_data)
9
+ expect(job.id).to eql('abcdef')
10
+ expect(job[:id]).to eql('abcdef')
11
+ expect(job.ready?).to eql(false)
12
+ end
13
+
14
+ it 'makes it easy to dress an instance' do
15
+ job = Job.full(a_job_data)
16
+ expect(job.id).to eql('abcdef')
17
+ expect(job[:id]).to eql('abcdef')
18
+ expect(job.ready?).to eql(false)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Jobs
5
+ describe CreateJob do
6
+
7
+ let(:request) do
8
+ {
9
+ isReady: false,
10
+ opClass: 'CowSay',
11
+ opInput: {},
12
+ opContext: {},
13
+ createdBy: 'blambeau',
14
+ }
15
+ end
16
+
17
+ let(:jobs_relvar) do
18
+ Bmg.mutable([])
19
+ end
20
+
21
+ let(:context) do
22
+ Context.new.with_world(startback_jobs: jobs_relvar)
23
+ end
24
+
25
+ subject do
26
+ CreateJob.new(request).bind({
27
+ context: context,
28
+ }).call
29
+ end
30
+
31
+ it 'creates a job' do
32
+ expect(subject).to be_a(Model::Job)
33
+ expect(subject.id).not_to be_nil
34
+ end
35
+
36
+ it 'inserts the job in the relvar' do
37
+ subject
38
+ expect(jobs_relvar.count).to eql(1)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Jobs
5
+ describe RunJob do
6
+
7
+ let(:job_data) do
8
+ a_job_data
9
+ end
10
+
11
+ let(:jobs_relvar) do
12
+ Bmg.mutable([job_data])
13
+ end
14
+
15
+ let(:context) do
16
+ Context.new.with_world(startback_jobs: jobs_relvar)
17
+ end
18
+
19
+ subject do
20
+ RunJob.new(id: 'abcdef').bind({
21
+ context: context,
22
+ }).call
23
+ end
24
+
25
+ it 'runs the job' do
26
+ expect(subject).to eql('Hello !!')
27
+ end
28
+
29
+ it 'updates the job' do
30
+ subject
31
+ job_info = jobs_relvar.one
32
+ expect(job_info[:opResult]).to eql('Hello !!')
33
+ expect(job_info[:isReady]).to eql(true)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Startback
4
+ module Jobs
5
+ describe 'Finitio schemas' do
6
+
7
+ it 'is correctly installed on stdlib' do
8
+ system = Finitio.system <<~FIO
9
+ @import startback/jobs
10
+
11
+ Job.Ref
12
+ FIO
13
+ expect {
14
+ system.dress({ id: "hello" })
15
+ }.not_to raise_error
16
+ end
17
+
18
+ end
19
+ end
20
+ end
data/tasks/test.rake ADDED
@@ -0,0 +1,13 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ namespace :test do
4
+
5
+ desc "Run RSpec unit tests"
6
+ RSpec::Core::RakeTask.new(:unit) do |t|
7
+ t.pattern = "spec/unit/**/test_*.rb"
8
+ t.rspec_opts = %{-Ilib -Ispec --color --backtrace --format progress --format RspecJunitFormatter --out spec/rspec-unit.xml}
9
+ end
10
+
11
+ task :all => [:unit]
12
+ end
13
+ task :test => :'test:all'
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: startback-jobs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.13.0
5
+ platform: ruby
6
+ authors:
7
+ - Bernard Lambeau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-05-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.6'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '4.0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.6'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '4.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec_junit_formatter
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 0.4.1
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '0.5'
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.4.1
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '0.5'
53
+ - !ruby/object:Gem::Dependency
54
+ name: webspicy
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.20.5
60
+ - - "<"
61
+ - !ruby/object:Gem::Version
62
+ version: '0.21'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 0.20.5
70
+ - - "<"
71
+ - !ruby/object:Gem::Version
72
+ version: '0.21'
73
+ - !ruby/object:Gem::Dependency
74
+ name: rake
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ type: :development
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ - !ruby/object:Gem::Dependency
88
+ name: rack-test
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ - !ruby/object:Gem::Dependency
102
+ name: bmg
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ - !ruby/object:Gem::Dependency
116
+ name: startback
117
+ requirement: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '='
120
+ - !ruby/object:Gem::Version
121
+ version: 0.13.0
122
+ type: :runtime
123
+ prerelease: false
124
+ version_requirements: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - '='
127
+ - !ruby/object:Gem::Version
128
+ version: 0.13.0
129
+ description: Asynchronous jobs on top of the Startback framework
130
+ email: blambeau@gmail.com
131
+ executables: []
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - Gemfile
136
+ - Rakefile
137
+ - lib/startback/ext.rb
138
+ - lib/startback/ext/support/operation_runner.rb
139
+ - lib/startback/ext/web/api.rb
140
+ - lib/startback/jobs.fio
141
+ - lib/startback/jobs.rb
142
+ - lib/startback/jobs/agent.rb
143
+ - lib/startback/jobs/api.rb
144
+ - lib/startback/jobs/event.rb
145
+ - lib/startback/jobs/event/job_created.rb
146
+ - lib/startback/jobs/event/job_ran.rb
147
+ - lib/startback/jobs/model.rb
148
+ - lib/startback/jobs/model/job.rb
149
+ - lib/startback/jobs/operation.rb
150
+ - lib/startback/jobs/operation/create_job.rb
151
+ - lib/startback/jobs/operation/run_job.rb
152
+ - lib/startback/jobs/services.rb
153
+ - lib/startback/jobs/support.rb
154
+ - lib/startback/jobs/support/job_result.rb
155
+ - lib/startback/jobs/support/job_result/embedded.rb
156
+ - lib/startback/jobs/support/job_result/not_ready.rb
157
+ - lib/startback/jobs/support/job_result/redirect.rb
158
+ - spec/spec_helper.rb
159
+ - spec/unit/api/test_job_result.rb
160
+ - spec/unit/model/test_job.rb
161
+ - spec/unit/operation/test_create_job.rb
162
+ - spec/unit/operation/test_run_job.rb
163
+ - spec/unit/test_finitio_schema.rb
164
+ - tasks/test.rake
165
+ homepage: http://www.enspirit.be
166
+ licenses:
167
+ - MIT
168
+ metadata: {}
169
+ post_install_message:
170
+ rdoc_options: []
171
+ require_paths:
172
+ - lib
173
+ required_ruby_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ requirements: []
184
+ rubygems_version: 3.3.7
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Asynchronous jobs on top of Startback
188
+ test_files: []