crabfarm 0.1.2 → 0.1.3
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 +4 -4
- data/lib/crabfarm.rb +5 -1
- data/lib/crabfarm/cli.rb +49 -26
- data/lib/crabfarm/configuration.rb +4 -10
- data/lib/crabfarm/context.rb +29 -9
- data/lib/crabfarm/context_factory.rb +31 -0
- data/lib/crabfarm/crabtrap_context.rb +57 -17
- data/lib/crabfarm/crabtrap_runner.rb +30 -8
- data/lib/crabfarm/engines/{safe_state_loop.rb → async_state_manager.rb} +20 -22
- data/lib/crabfarm/engines/sync_state_manager.rb +40 -0
- data/lib/crabfarm/errors.rb +14 -7
- data/lib/crabfarm/global_state.rb +22 -0
- data/lib/crabfarm/modes/console.rb +13 -22
- data/lib/crabfarm/modes/generator.rb +6 -15
- data/lib/crabfarm/modes/publisher.rb +1 -1
- data/lib/crabfarm/modes/recorder.rb +26 -21
- data/lib/crabfarm/modes/server.rb +4 -4
- data/lib/crabfarm/phantom_runner.rb +12 -30
- data/lib/crabfarm/rspec.rb +27 -27
- data/lib/crabfarm/templates/Crabfile.erb +5 -2
- data/lib/crabfarm/templates/spec_helper.rb.erb +0 -2
- data/lib/crabfarm/transition_service.rb +1 -1
- data/lib/crabfarm/utils/port_discovery.rb +17 -0
- data/lib/crabfarm/version.rb +1 -1
- metadata +9 -6
- data/lib/crabfarm/event_store.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c10577d223677baa807f27aa55fc8f2ccf19f189
|
4
|
+
data.tar.gz: 7d07015295fe0325a85d73396821872e0e3542d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45015ef058a82381fc1db17791bb99c362c37c8bf0cf24e29d0862c76c44f006c47e60f6d2689b545be7ec564ce05857565ca7bc00d43f592cba0f58a58f658e
|
7
|
+
data.tar.gz: 83dc7148c8ed7b793290b0c197ad6ad10b1853d196d5c650a471cd4a26531d424177a303d82a25a4780a806d0b075683234318bef9f10f0ed1283f03f807d4df
|
data/lib/crabfarm.rb
CHANGED
@@ -7,7 +7,7 @@ require "selenium-webdriver"
|
|
7
7
|
require "crabfarm/version"
|
8
8
|
require "crabfarm/errors"
|
9
9
|
require "crabfarm/configuration"
|
10
|
-
require "crabfarm/
|
10
|
+
require "crabfarm/global_state"
|
11
11
|
require "crabfarm/driver_bucket"
|
12
12
|
require "crabfarm/driver_bucket_pool"
|
13
13
|
require "crabfarm/http_client"
|
@@ -16,10 +16,14 @@ require "crabfarm/phantom_driver_factory"
|
|
16
16
|
require "crabfarm/phantom_runner"
|
17
17
|
require "crabfarm/state_store"
|
18
18
|
require "crabfarm/context"
|
19
|
+
require "crabfarm/context_factory"
|
20
|
+
require "crabfarm/transition_service"
|
19
21
|
require "crabfarm/base_state"
|
20
22
|
require "crabfarm/base_parser"
|
21
23
|
require "crabfarm/strategies"
|
22
24
|
|
25
|
+
require "crabfarm/utils/port_discovery"
|
26
|
+
|
23
27
|
module Crabfarm
|
24
28
|
|
25
29
|
@@config = Configuration.new
|
data/lib/crabfarm/cli.rb
CHANGED
@@ -10,28 +10,20 @@ module Crabfarm
|
|
10
10
|
desc "Starts the crawler in console mode"
|
11
11
|
command [:console, :c] do |c|
|
12
12
|
|
13
|
-
c.desc "
|
14
|
-
c.flag :
|
15
|
-
|
16
|
-
c.desc "Replay from crabtrap file"
|
17
|
-
c.flag :replay
|
13
|
+
c.desc "Use a recorded memento as data source, requires crabtrap"
|
14
|
+
c.flag [:m, :memento]
|
18
15
|
|
19
16
|
Support::GLI.generate_options c
|
20
17
|
|
21
18
|
c.action do |global_options,options,args|
|
22
|
-
next puts "This command can only be run inside a crabfarm application" unless
|
19
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
23
20
|
|
24
21
|
Crabfarm.config.set Support::GLI.parse_options options
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
context.capture options[:capture] if options[:capture]
|
31
|
-
context.replay options[:replay] if options[:replay]
|
32
|
-
|
33
|
-
require "crabfarm/modes/console"
|
34
|
-
Crabfarm::Modes::Console.start context
|
23
|
+
ContextFactory.with_context options[:memento] do |context|
|
24
|
+
require "crabfarm/modes/console"
|
25
|
+
Crabfarm::Modes::Console.process_input context
|
26
|
+
end
|
35
27
|
end
|
36
28
|
end
|
37
29
|
|
@@ -46,6 +38,9 @@ module Crabfarm
|
|
46
38
|
c.desc "Set the server min and max threads, defaults to 0:16"
|
47
39
|
c.flag [:t,:threads]
|
48
40
|
|
41
|
+
c.desc "Use a recorded memento as data source, requires crabtrap"
|
42
|
+
c.flag [:m, :memento]
|
43
|
+
|
49
44
|
c.desc "Start the server in verbose mode"
|
50
45
|
c.switch :verbose, :default_value => false
|
51
46
|
|
@@ -55,18 +50,22 @@ module Crabfarm
|
|
55
50
|
Support::GLI.generate_options c
|
56
51
|
|
57
52
|
c.action do |global_options,options,args|
|
58
|
-
next puts "This command can only be run inside a crabfarm application" unless
|
53
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
54
|
+
|
55
|
+
Crabfarm.config.set Support::GLI.parse_options options
|
56
|
+
|
57
|
+
ActiveSupport::Dependencies.mechanism = :require unless options[:reload]
|
59
58
|
|
60
|
-
require "crabfarm/modes/server"
|
61
59
|
server_options = {}
|
62
60
|
server_options[:Host] = options[:host] unless options[:host].nil?
|
63
61
|
server_options[:Port] = options[:port] || 3100
|
64
62
|
server_options[:Threads] = options[:threads] unless options[:threads].nil?
|
65
63
|
server_options[:Verbose] = options[:verbose]
|
66
64
|
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
ContextFactory.with_context options[:memento] do |context|
|
66
|
+
require "crabfarm/modes/server"
|
67
|
+
Crabfarm::Modes::Server.serve context, server_options
|
68
|
+
end
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
@@ -79,6 +78,8 @@ module Crabfarm
|
|
79
78
|
app.flag [:r, :remote]
|
80
79
|
|
81
80
|
app.action do |global_options,options,args|
|
81
|
+
next puts "This command cannot be run inside a crabfarm application" if GlobalState.inside_crawler_app?
|
82
|
+
|
82
83
|
require "crabfarm/modes/generator"
|
83
84
|
Crabfarm::Modes::Generator.generate_app(Dir.pwd, args[0], options[:remote])
|
84
85
|
end
|
@@ -87,27 +88,34 @@ module Crabfarm
|
|
87
88
|
c.desc "Generates a new crabfarm parser and parser spec"
|
88
89
|
c.command :parser do |parser|
|
89
90
|
parser.action do |global_options,options,args|
|
91
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
92
|
+
|
90
93
|
require "crabfarm/modes/generator"
|
91
|
-
Crabfarm::Modes::Generator.generate_parser(args[0])
|
94
|
+
Crabfarm::Modes::Generator.generate_parser(GlobalState.app_path, args[0])
|
92
95
|
end
|
93
96
|
end
|
94
97
|
|
95
98
|
c.desc "Generates a new crabfarm state and parser spec"
|
96
99
|
c.command :state do |parser|
|
97
100
|
parser.action do |global_options,options,args|
|
101
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
102
|
+
|
98
103
|
require "crabfarm/modes/generator"
|
99
|
-
Crabfarm::Modes::Generator.generate_state(args[0])
|
104
|
+
Crabfarm::Modes::Generator.generate_state(GlobalState.app_path, args[0])
|
100
105
|
end
|
101
106
|
end
|
102
107
|
end
|
103
108
|
|
104
109
|
desc "Perform an HTTP recording for use in tests"
|
105
110
|
command [:record, :r] do |c|
|
111
|
+
c.desc "Run recorder in playback mode"
|
112
|
+
c.switch [:p, :playback], :default_value => false
|
113
|
+
|
106
114
|
c.action do |global_options, options, args|
|
107
|
-
next puts "This command can only be run inside a crabfarm application" unless
|
115
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
108
116
|
|
109
117
|
require "crabfarm/modes/recorder"
|
110
|
-
Crabfarm::Modes::Recorder.start args[0]
|
118
|
+
Crabfarm::Modes::Recorder.start GlobalState.memento_path(args[0]), options[:playback]
|
111
119
|
end
|
112
120
|
end
|
113
121
|
|
@@ -120,12 +128,27 @@ module Crabfarm
|
|
120
128
|
c.switch :unsafe, :default_value => false
|
121
129
|
|
122
130
|
c.action do |global_options,options,args|
|
123
|
-
next puts "This command can only be run inside a crabfarm application" unless
|
131
|
+
next puts "This command can only be run inside a crabfarm application" unless GlobalState.inside_crawler_app?
|
124
132
|
|
125
133
|
options[:remote] = args[0]
|
126
134
|
|
127
135
|
require "crabfarm/modes/publisher"
|
128
|
-
Crabfarm::Modes::Publisher.publish
|
136
|
+
Crabfarm::Modes::Publisher.publish GlobalState.app_path, options
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
on_error do |exc|
|
141
|
+
case exc
|
142
|
+
when BinaryMissingError
|
143
|
+
if exc.binary == 'phantomjs'
|
144
|
+
puts "Could not find the phantomjs binary at '#{exc.path}', try installing it using 'npm install phantomjs -g' or set the propper path in your project's Crabfile"
|
145
|
+
false
|
146
|
+
elsif exc.binary == 'crabtrap'
|
147
|
+
puts "Could not find the crabtrap binary at '#{exc.path}', try installing it using 'npm install crabtrap -g' or set the propper path in your project's Crabfile"
|
148
|
+
false
|
149
|
+
else true end
|
150
|
+
else
|
151
|
+
true
|
129
152
|
end
|
130
153
|
end
|
131
154
|
|
@@ -25,12 +25,12 @@ module Crabfarm
|
|
25
25
|
[:phantom_load_images, :boolean, 'Phantomjs image loading, only for phantomjs driver.'],
|
26
26
|
[:phantom_ssl, ['sslv3', 'sslv2', 'tlsv1', 'any'], 'Phantomjs ssl mode: sslv3, sslv2, tlsv1 or any, only for phantomjs driver.'],
|
27
27
|
[:phantom_bin_path, :string, 'Phantomjs binary path, only for phantomjs driver.'],
|
28
|
-
[:phantom_lock_file, :string, 'Phantomjs lock file path, only for phantomjs driver.'],
|
29
28
|
|
30
29
|
# Crabtrap launcher configuration
|
31
30
|
[:crabtrap_bin_path, :string, 'Crabtrap binary path.'],
|
32
|
-
|
33
|
-
|
31
|
+
|
32
|
+
# Recorder configuration
|
33
|
+
[:recorder_driver, :string, 'Recorder driver name, defaults to \'firefox\'']
|
34
34
|
]
|
35
35
|
.map { |o| Option.new *o }
|
36
36
|
|
@@ -56,7 +56,6 @@ module Crabfarm
|
|
56
56
|
driver_factory: nil,
|
57
57
|
log_path: nil,
|
58
58
|
proxy: nil,
|
59
|
-
|
60
59
|
driver: 'phantomjs',
|
61
60
|
driver_capabilities: Selenium::WebDriver::Remote::Capabilities.firefox,
|
62
61
|
driver_host: 'localhost',
|
@@ -64,14 +63,11 @@ module Crabfarm
|
|
64
63
|
driver_remote_timeout: 120,
|
65
64
|
driver_window_width: 1280,
|
66
65
|
driver_window_height: 800,
|
67
|
-
|
68
66
|
phantom_load_images: false,
|
69
67
|
phantom_ssl: 'any',
|
70
68
|
phantom_bin_path: 'phantomjs',
|
71
|
-
phantom_lock_file: nil,
|
72
|
-
|
73
69
|
crabtrap_bin_path: 'crabtrap',
|
74
|
-
|
70
|
+
recorder_driver: :firefox
|
75
71
|
}
|
76
72
|
end
|
77
73
|
|
@@ -108,7 +104,6 @@ module Crabfarm
|
|
108
104
|
proxy: proxy,
|
109
105
|
ssl: phantom_ssl,
|
110
106
|
bin_path: phantom_bin_path,
|
111
|
-
lock_file: phantom_lock_file,
|
112
107
|
log_file: log_path ? File.join(log_path, 'phantom.log') : nil
|
113
108
|
}
|
114
109
|
end
|
@@ -116,7 +111,6 @@ module Crabfarm
|
|
116
111
|
def crabtrap_config
|
117
112
|
{
|
118
113
|
bin_path: crabtrap_bin_path,
|
119
|
-
port: crabtrap_port,
|
120
114
|
proxy: proxy
|
121
115
|
}
|
122
116
|
end
|
data/lib/crabfarm/context.rb
CHANGED
@@ -11,26 +11,45 @@ module Crabfarm
|
|
11
11
|
@loaded = false
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def loaded?
|
15
|
+
@loaded
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare
|
19
|
+
unless @loaded
|
20
|
+
load_services
|
21
|
+
@loaded = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
reset_services if @loaded
|
27
|
+
end
|
28
|
+
|
29
|
+
def release
|
30
|
+
unload_services
|
31
|
+
@loaded = false
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def load_services
|
15
37
|
init_phantom_if_required
|
16
38
|
init_driver_pool
|
17
39
|
init_http_client
|
18
|
-
@loaded = true
|
19
40
|
end
|
20
41
|
|
21
|
-
def
|
42
|
+
def reset_services
|
22
43
|
@store.reset
|
23
|
-
@pool.reset
|
44
|
+
@pool.reset
|
24
45
|
end
|
25
46
|
|
26
|
-
def
|
47
|
+
def unload_services
|
27
48
|
release_driver_pool
|
49
|
+
release_http_client
|
28
50
|
release_phantom
|
29
|
-
@loaded = false
|
30
51
|
end
|
31
52
|
|
32
|
-
private
|
33
|
-
|
34
53
|
def init_driver_pool
|
35
54
|
@pool = DriverBucketPool.new build_driver_factory if @pool.nil?
|
36
55
|
end
|
@@ -47,7 +66,8 @@ module Crabfarm
|
|
47
66
|
end
|
48
67
|
|
49
68
|
def load_and_start_phantom
|
50
|
-
|
69
|
+
phantom_port = Utils::PortDiscovery.find_available_port
|
70
|
+
new_phantom = PhantomRunner.new phantom_config.merge(port: phantom_port)
|
51
71
|
new_phantom.start
|
52
72
|
return new_phantom
|
53
73
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Crabfarm
|
2
|
+
module ContextFactory
|
3
|
+
|
4
|
+
def with_context(_memento=nil)
|
5
|
+
ctx = build_context(_memento)
|
6
|
+
begin
|
7
|
+
ctx.prepare
|
8
|
+
yield ctx
|
9
|
+
ensure
|
10
|
+
ctx.release
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_context(_memento=nil)
|
15
|
+
if _memento.nil?
|
16
|
+
Crabfarm::Context.new
|
17
|
+
else
|
18
|
+
load_crabtrap_context _memento
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_crabtrap_context(_memento)
|
23
|
+
require 'crabfarm/crabtrap_context'
|
24
|
+
m_path = GlobalState.memento_path _memento
|
25
|
+
raise ResourceNotFoundError.new "Could not find memento '#{_name}'" unless File.exists? m_path
|
26
|
+
Crabfarm::CrabtrapContext.new :replay, m_path
|
27
|
+
end
|
28
|
+
|
29
|
+
extend self
|
30
|
+
end
|
31
|
+
end
|
@@ -4,54 +4,94 @@ require 'crabfarm/crabtrap_runner'
|
|
4
4
|
module Crabfarm
|
5
5
|
class CrabtrapContext < Context
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
attr_accessor :mode
|
8
|
+
|
9
|
+
def initialize(_mode=:pass, _path=nil)
|
10
|
+
@mode = _mode
|
11
|
+
@path = _path
|
10
12
|
end
|
11
13
|
|
12
14
|
def pass_through
|
13
|
-
|
15
|
+
if not loaded? or @mode != :pass
|
16
|
+
@mode = :pass
|
17
|
+
@path = nil
|
18
|
+
restart
|
19
|
+
end
|
14
20
|
end
|
15
21
|
|
16
22
|
def capture(_path)
|
17
|
-
|
23
|
+
@mode = :capture
|
24
|
+
@path = _path
|
25
|
+
restart
|
18
26
|
end
|
19
27
|
|
20
28
|
def replay(_path)
|
21
|
-
|
29
|
+
@mode = :replay
|
30
|
+
@path = _path
|
31
|
+
restart
|
22
32
|
end
|
23
33
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
34
|
+
def restart
|
35
|
+
if not loaded?
|
36
|
+
prepare
|
37
|
+
else
|
38
|
+
stop_daemon
|
39
|
+
start_daemon
|
40
|
+
end
|
27
41
|
end
|
28
42
|
|
29
43
|
private
|
30
44
|
|
45
|
+
def load_services
|
46
|
+
@port = Utils::PortDiscovery.find_available_port
|
47
|
+
start_daemon
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def reset_services
|
52
|
+
restart
|
53
|
+
end
|
54
|
+
|
55
|
+
def unload_services
|
56
|
+
super
|
57
|
+
stop_daemon
|
58
|
+
@port = nil
|
59
|
+
end
|
60
|
+
|
31
61
|
def build_http_client
|
32
62
|
HttpClient.new proxy_address
|
33
63
|
end
|
34
64
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
65
|
+
def start_daemon
|
66
|
+
if @runner.nil?
|
67
|
+
options = {
|
68
|
+
mode: @mode,
|
69
|
+
bucket_path: @path,
|
70
|
+
port: @port
|
71
|
+
}
|
72
|
+
|
73
|
+
@runner = CrabtrapRunner.new Crabfarm.config.crabtrap_config.merge(options)
|
74
|
+
@runner.start
|
75
|
+
end
|
39
76
|
end
|
40
77
|
|
41
78
|
def stop_daemon
|
42
|
-
|
79
|
+
unless @runner.nil?
|
80
|
+
@runner.stop
|
81
|
+
@runner = nil
|
82
|
+
else nil end
|
43
83
|
end
|
44
84
|
|
45
85
|
def driver_config
|
46
|
-
|
86
|
+
super.merge(proxy: proxy_address)
|
47
87
|
end
|
48
88
|
|
49
89
|
def phantom_config
|
50
|
-
|
90
|
+
super.merge(proxy: proxy_address)
|
51
91
|
end
|
52
92
|
|
53
93
|
def proxy_address
|
54
|
-
"127.0.0.1:#{@
|
94
|
+
"127.0.0.1:#{@port}"
|
55
95
|
end
|
56
96
|
|
57
97
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
1
3
|
module Crabfarm
|
2
4
|
class CrabtrapRunner
|
3
5
|
|
6
|
+
CRABTRAP_START_TM = 5 # seconds
|
7
|
+
|
4
8
|
def initialize(_config={})
|
5
9
|
@config = _config;
|
6
10
|
@pid = nil
|
@@ -11,7 +15,7 @@ module Crabfarm
|
|
11
15
|
end
|
12
16
|
|
13
17
|
def port
|
14
|
-
@config[:port]
|
18
|
+
@config[:port]
|
15
19
|
end
|
16
20
|
|
17
21
|
def mode
|
@@ -19,25 +23,39 @@ module Crabfarm
|
|
19
23
|
end
|
20
24
|
|
21
25
|
def start
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
rescue
|
26
|
-
puts "Could not find crabtrap at #{@config[:bin_path]}, memento replaying is disabled!"
|
27
|
-
@pid = nil
|
28
|
-
end
|
26
|
+
logger.info "Starting crabtrap in port #{port}"
|
27
|
+
@pid = spawn_crabtrap
|
28
|
+
logger.info "Crabtrap started (PID: #{@pid})"
|
29
29
|
end
|
30
30
|
|
31
31
|
def stop
|
32
32
|
unless @pid.nil?
|
33
|
+
logger.info "Stopping crabtrap (PID: #{@pid})"
|
33
34
|
Process.kill("INT", @pid)
|
34
35
|
Process.wait @pid
|
36
|
+
logger.info "Crabtrap stopped"
|
35
37
|
@pid = nil
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
39
41
|
private
|
40
42
|
|
43
|
+
def spawn_crabtrap
|
44
|
+
pid = nil
|
45
|
+
begin
|
46
|
+
pid = Process.spawn({}, crabtrap_cmd)
|
47
|
+
Timeout::timeout(CRABTRAP_START_TM) { wait_for_server }
|
48
|
+
return pid
|
49
|
+
rescue Errno::ENOENT
|
50
|
+
raise BinaryMissingError.new 'crabtrap', @config[:bin_path]
|
51
|
+
rescue Timeout::Error
|
52
|
+
Process.kill "INT", pid
|
53
|
+
Process.wait pid
|
54
|
+
raise
|
55
|
+
end
|
56
|
+
pid
|
57
|
+
end
|
58
|
+
|
41
59
|
def crabtrap_cmd
|
42
60
|
cmd = [@config[:bin_path]]
|
43
61
|
cmd << mode.to_s
|
@@ -57,5 +75,9 @@ module Crabfarm
|
|
57
75
|
end
|
58
76
|
end
|
59
77
|
|
78
|
+
def logger
|
79
|
+
Crabfarm.logger
|
80
|
+
end
|
81
|
+
|
60
82
|
end
|
61
83
|
end
|
@@ -3,11 +3,12 @@ require 'ostruct'
|
|
3
3
|
|
4
4
|
module Crabfarm
|
5
5
|
module Engines
|
6
|
-
class
|
6
|
+
class AsyncStateManager
|
7
7
|
|
8
8
|
class LoopAbortedException < StandardError; end
|
9
9
|
|
10
|
-
def initialize
|
10
|
+
def initialize(_context)
|
11
|
+
@context = _context
|
11
12
|
@working = false
|
12
13
|
@fatal = nil
|
13
14
|
@lock = Mutex.new
|
@@ -37,7 +38,7 @@ module Crabfarm
|
|
37
38
|
start
|
38
39
|
end
|
39
40
|
|
40
|
-
def
|
41
|
+
def transition(_name, _params={}, _wait=nil)
|
41
42
|
@lock.synchronize {
|
42
43
|
if @fatal
|
43
44
|
raise CrawlerError.new @fatal
|
@@ -100,25 +101,24 @@ module Crabfarm
|
|
100
101
|
end
|
101
102
|
|
102
103
|
def crawl_loop
|
103
|
-
context = Crabfarm::Context.new
|
104
|
-
|
105
104
|
begin
|
106
105
|
loop do
|
107
106
|
if @working
|
108
|
-
|
109
|
-
|
107
|
+
begin
|
108
|
+
logger.info "Transitioning state: #{@next_state_name}"
|
109
|
+
@elapsed = Benchmark.measure do
|
110
110
|
ActiveSupport::Dependencies.clear
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
end
|
111
|
+
@doc = TransitionService.apply_state(@context, @next_state_name, @next_state_params).output_as_json
|
112
|
+
end.real
|
113
|
+
|
114
|
+
logger.info "Transitioned in #{@elapsed.real}"
|
115
|
+
@error = nil
|
116
|
+
rescue Exception => e
|
117
|
+
logger.error "Error during transition:"
|
118
|
+
logger.error e
|
119
|
+
@doc = nil
|
120
|
+
@error = e
|
121
|
+
end
|
122
122
|
|
123
123
|
@lock.synchronize {
|
124
124
|
@state_name = @next_state_name
|
@@ -128,17 +128,15 @@ module Crabfarm
|
|
128
128
|
else sleep 0.2 end
|
129
129
|
end
|
130
130
|
rescue LoopAbortedException
|
131
|
-
logger.info "
|
131
|
+
logger.info "Manager stopping"
|
132
132
|
|
133
133
|
rescue Exception => e
|
134
|
-
logger.fatal "
|
134
|
+
logger.fatal "Unhandled exception:"
|
135
135
|
logger.fatal e
|
136
136
|
|
137
137
|
@lock.synchronize {
|
138
138
|
@fatal = e
|
139
139
|
}
|
140
|
-
ensure
|
141
|
-
context.release
|
142
140
|
end
|
143
141
|
end
|
144
142
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Crabfarm
|
5
|
+
module Engines
|
6
|
+
class SyncStateManager
|
7
|
+
|
8
|
+
def initialize(_context)
|
9
|
+
@context = _context
|
10
|
+
@lock = Mutex.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def reload!
|
14
|
+
@lock.synchronize {
|
15
|
+
ActiveSupport::Dependencies.clear
|
16
|
+
@context.reset
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset
|
21
|
+
@lock.synchronize {
|
22
|
+
@context.reset
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def transition(_name, _params={})
|
27
|
+
@lock.synchronize {
|
28
|
+
output = { name: _name, params: _params }
|
29
|
+
|
30
|
+
output[:elapsed] = Benchmark.measure do
|
31
|
+
output[:doc] = TransitionService.apply_state(@context, _name, _params).output_as_json
|
32
|
+
end
|
33
|
+
|
34
|
+
OpenStruct.new output
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/crabfarm/errors.rb
CHANGED
@@ -4,18 +4,25 @@ module Crabfarm
|
|
4
4
|
|
5
5
|
class ConfigurationError < Error; end
|
6
6
|
|
7
|
-
class
|
7
|
+
class BinaryMissingError < ConfigurationError
|
8
8
|
|
9
|
-
|
10
|
-
attr_accessor :
|
9
|
+
attr_accessor :binary
|
10
|
+
attr_accessor :path
|
11
11
|
|
12
|
-
def initialize(
|
13
|
-
|
14
|
-
@
|
15
|
-
|
12
|
+
def initialize(_binary, _path)
|
13
|
+
@binary = _binary
|
14
|
+
@path = _path
|
15
|
+
super "Could not find a suitable version of #{@binary}"
|
16
16
|
end
|
17
|
+
|
17
18
|
end
|
18
19
|
|
20
|
+
class AssertionError < Error; end
|
21
|
+
|
22
|
+
class ArgumentError < Error; end
|
23
|
+
|
24
|
+
class ResourceNotFoundError < Crabfarm::Error; end
|
25
|
+
|
19
26
|
class ApiError < Error
|
20
27
|
def code; 500 end
|
21
28
|
def to_json; {} end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Crabfarm
|
2
|
+
module GlobalState
|
3
|
+
|
4
|
+
def inside_crawler_app?
|
5
|
+
defined? CF_PATH
|
6
|
+
end
|
7
|
+
|
8
|
+
def app_path
|
9
|
+
CF_PATH
|
10
|
+
end
|
11
|
+
|
12
|
+
def memento_path(_name)
|
13
|
+
File.join(app_path, 'spec/mementos', _name + '.json.gz')
|
14
|
+
end
|
15
|
+
|
16
|
+
def snapshot_path(_file)
|
17
|
+
File.join(app_path, 'spec/snapshots', _file)
|
18
|
+
end
|
19
|
+
|
20
|
+
extend self
|
21
|
+
end
|
22
|
+
end
|
@@ -1,28 +1,23 @@
|
|
1
|
-
require 'benchmark'
|
2
1
|
require 'readline'
|
3
2
|
require 'rainbow'
|
4
3
|
require 'rainbow/ext/string'
|
5
4
|
require 'json'
|
5
|
+
require 'crabfarm/engines/sync_state_loop'
|
6
6
|
|
7
7
|
module Crabfarm
|
8
8
|
module Modes
|
9
9
|
class Console
|
10
10
|
|
11
|
-
class ConsoleDsl
|
12
|
-
|
13
|
-
def initialize(_context)
|
14
|
-
@context = _context
|
15
|
-
end
|
11
|
+
class ConsoleDsl < Engines::SyncStateManager
|
16
12
|
|
17
13
|
def reload!
|
18
14
|
puts "Reloading crawler source".color(:green)
|
19
|
-
|
20
|
-
@context.reset
|
15
|
+
super
|
21
16
|
end
|
22
17
|
|
23
18
|
def reset
|
24
19
|
puts "Resetting crawling context".color(:green)
|
25
|
-
|
20
|
+
super
|
26
21
|
end
|
27
22
|
|
28
23
|
def transition(_name=nil, _params={})
|
@@ -32,17 +27,14 @@ module Crabfarm
|
|
32
27
|
end
|
33
28
|
|
34
29
|
begin
|
35
|
-
|
36
|
-
|
37
|
-
doc = TransitionService.apply_state(@context, _name, _params).output_as_json
|
30
|
+
puts "Transitioning to #{_name.to_s.camelize} state"
|
31
|
+
output = super
|
38
32
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
rescue
|
44
|
-
puts "#{e.to_s}".color(:red)
|
45
|
-
rescue => e
|
33
|
+
puts "State changed, generated document:"
|
34
|
+
puts JSON.pretty_generate(output.doc).color(:green).gsub(/(^|\\n)/, ' ')
|
35
|
+
puts "Completed in #{output.elapsed.real} s"
|
36
|
+
|
37
|
+
rescue Exception => e
|
46
38
|
puts "#{e.to_s}".color(:red)
|
47
39
|
puts e.backtrace
|
48
40
|
end
|
@@ -56,7 +48,7 @@ module Crabfarm
|
|
56
48
|
alias :r :reset
|
57
49
|
end
|
58
50
|
|
59
|
-
def self.
|
51
|
+
def self.process_input(_context)
|
60
52
|
dsl = ConsoleDsl.new _context
|
61
53
|
|
62
54
|
loop do
|
@@ -71,8 +63,7 @@ module Crabfarm
|
|
71
63
|
end
|
72
64
|
end
|
73
65
|
|
74
|
-
puts "
|
75
|
-
_context.release
|
66
|
+
puts "Exiting".color(:green)
|
76
67
|
end
|
77
68
|
|
78
69
|
end
|
@@ -9,7 +9,7 @@ module Crabfarm
|
|
9
9
|
module Generator
|
10
10
|
|
11
11
|
def generate_app(_target, _name, _default_remote=nil)
|
12
|
-
|
12
|
+
with_base_path _target do
|
13
13
|
binding = {
|
14
14
|
name: _name,
|
15
15
|
remote: _default_remote,
|
@@ -35,38 +35,29 @@ module Crabfarm
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def generate_state(_name)
|
38
|
+
def generate_state(_target, _name)
|
39
39
|
class_name = _name.camelize
|
40
|
-
|
40
|
+
with_base_path _target do
|
41
41
|
binding = { state_class: class_name.camelize }
|
42
42
|
path('app', 'states', class_name.underscore + '.rb').render('state.rb', binding)
|
43
43
|
path('spec', 'states', class_name.underscore + '_spec.rb').render('state_spec.rb', binding)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def generate_parser(_name)
|
47
|
+
def generate_parser(_target, _name)
|
48
48
|
class_name = _name.camelize + 'Parser'
|
49
|
-
|
49
|
+
with_base_path _target do
|
50
50
|
binding = { parser_class: class_name }
|
51
51
|
path('app', 'parsers', class_name.underscore + '.rb').render('parser.rb', binding)
|
52
52
|
path('spec', 'parsers', class_name.underscore + '_spec.rb').render('parser_spec.rb', binding)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
56
|
+
def with_base_path(_target)
|
57
57
|
@base_path = _target
|
58
58
|
yield
|
59
59
|
end
|
60
60
|
|
61
|
-
def with_crawler_path
|
62
|
-
if defined? CF_PATH
|
63
|
-
@base_path = CF_PATH
|
64
|
-
yield
|
65
|
-
else
|
66
|
-
puts "This command can only be run inside a crabfarm application"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
61
|
def path(*_args)
|
71
62
|
@path = _args
|
72
63
|
self
|
@@ -4,37 +4,42 @@ require 'crabfarm/crabtrap_runner'
|
|
4
4
|
|
5
5
|
module Crabfarm
|
6
6
|
module Modes
|
7
|
-
|
7
|
+
module Recorder
|
8
8
|
|
9
|
-
def self.start(_target)
|
10
|
-
return puts "Must provide a recording
|
9
|
+
def self.start(_target, _replay=false)
|
10
|
+
return puts "Must provide a recording target" unless _target.is_a? String
|
11
|
+
return puts "Memento file does not exist: #{_target}" if _replay and not File.exist? _target
|
11
12
|
|
12
13
|
crabtrap_config = Crabfarm.config.crabtrap_config
|
13
|
-
crabtrap_config[:mode] = :capture
|
14
|
-
crabtrap_config[:
|
14
|
+
crabtrap_config[:mode] = _replay ? :replay : :capture
|
15
|
+
crabtrap_config[:port] = Utils::PortDiscovery.find_available_port
|
16
|
+
crabtrap_config[:bucket_path] = _target
|
15
17
|
|
16
18
|
crabtrap = CrabtrapRunner.new crabtrap_config
|
17
19
|
crabtrap.start
|
18
20
|
|
19
|
-
driver_config = Crabfarm.config.driver_config
|
20
|
-
driver_config[:name] = :firefox
|
21
|
-
driver_config[:proxy] = "127.0.0.1:#{crabtrap.port}"
|
22
|
-
|
23
|
-
driver = DefaultDriverFactory.new(driver_config).build_driver nil
|
24
|
-
|
25
21
|
begin
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
driver_config = Crabfarm.config.driver_config
|
23
|
+
driver_config[:name] = Crabfarm.config.recorder_driver
|
24
|
+
driver_config[:proxy] = "127.0.0.1:#{crabtrap.port}"
|
25
|
+
|
26
|
+
driver = DefaultDriverFactory.new(driver_config).build_driver nil
|
27
|
+
|
28
|
+
begin
|
29
|
+
puts "Press Ctrl-C to stop capturing."
|
30
|
+
loop do
|
31
|
+
driver.current_url
|
32
|
+
sleep 1.0
|
33
|
+
end
|
34
|
+
rescue Selenium::WebDriver::Error::WebDriverError, SystemExit, Interrupt
|
35
|
+
# noop
|
30
36
|
end
|
31
|
-
rescue Selenium::WebDriver::Error::WebDriverError, SystemExit, Interrupt
|
32
|
-
# noop
|
33
|
-
end
|
34
37
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
puts "Releasing crawling context".color(:green)
|
39
|
+
driver.quit rescue nil
|
40
|
+
ensure
|
41
|
+
crabtrap.stop
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'grape'
|
2
2
|
require 'crabfarm/support/custom_puma'
|
3
|
-
require 'crabfarm/engines/
|
3
|
+
require 'crabfarm/engines/async_state_manager'
|
4
4
|
|
5
5
|
module Crabfarm
|
6
6
|
module Modes
|
@@ -54,7 +54,7 @@ module Crabfarm
|
|
54
54
|
optional :wait, type: Float
|
55
55
|
end
|
56
56
|
put :state do
|
57
|
-
print_state evaluator.
|
57
|
+
print_state evaluator.transition params[:name], params[:params], wait
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -62,8 +62,8 @@ module Crabfarm
|
|
62
62
|
@@evaluator
|
63
63
|
end
|
64
64
|
|
65
|
-
def self.
|
66
|
-
@@evaluator = Engines::
|
65
|
+
def self.serve(_context, _options)
|
66
|
+
@@evaluator = Engines::AsyncStateManager.new _context
|
67
67
|
@@evaluator.start
|
68
68
|
begin
|
69
69
|
Support::CustomPuma.run API, _options
|
@@ -5,16 +5,17 @@ module Crabfarm
|
|
5
5
|
|
6
6
|
PHANTOM_START_TM = 5 # seconds
|
7
7
|
|
8
|
-
attr_reader :port
|
9
|
-
|
10
8
|
def initialize(_config={})
|
11
9
|
@config = _config;
|
12
10
|
@pid = nil
|
13
11
|
end
|
14
12
|
|
13
|
+
def port
|
14
|
+
@config[:port]
|
15
|
+
end
|
16
|
+
|
15
17
|
def start
|
16
|
-
|
17
|
-
Crabfarm.logger.info "Starting phantomjs in port #{@port}"
|
18
|
+
Crabfarm.logger.info "Starting phantomjs in port #{port}"
|
18
19
|
@pid = spawn_phantomjs
|
19
20
|
Crabfarm.logger.info "Phantomjs started (PID: #{@pid})"
|
20
21
|
end
|
@@ -32,22 +33,25 @@ module Crabfarm
|
|
32
33
|
private
|
33
34
|
|
34
35
|
def spawn_phantomjs
|
35
|
-
pid =
|
36
|
+
pid = nil
|
36
37
|
begin
|
38
|
+
pid = Process.spawn({}, phantomjs_cmd)
|
37
39
|
Timeout::timeout(PHANTOM_START_TM) { wait_for_server }
|
40
|
+
return pid
|
41
|
+
rescue Errno::ENOENT
|
42
|
+
raise BinaryMissingError.new 'phantomjs', @config[:bin_path]
|
38
43
|
rescue Timeout::Error
|
39
44
|
Process.kill "INT", pid
|
40
45
|
Process.wait pid
|
41
46
|
raise
|
42
47
|
end
|
43
|
-
return pid
|
44
48
|
end
|
45
49
|
|
46
50
|
def phantomjs_cmd
|
47
51
|
cmd = [@config[:bin_path]]
|
48
52
|
cmd << '--load-images=false' unless @config[:load_images]
|
49
53
|
cmd << "--proxy=#{@config[:proxy]}" unless @config[:proxy].nil?
|
50
|
-
cmd << "--webdriver=#{
|
54
|
+
cmd << "--webdriver=#{port}"
|
51
55
|
cmd << "--ssl-protocol=#{@config[:ssl]}" unless @config[:ssl].nil?
|
52
56
|
cmd << "--ignore-ssl-errors=true"
|
53
57
|
cmd << "--webdriver-loglevel=WARN"
|
@@ -55,37 +59,15 @@ module Crabfarm
|
|
55
59
|
cmd.join(' ')
|
56
60
|
end
|
57
61
|
|
58
|
-
def find_available_port
|
59
|
-
with_lock do
|
60
|
-
socket = Socket.new(:INET, :STREAM, 0)
|
61
|
-
socket.bind(Addrinfo.tcp("127.0.0.1", 0))
|
62
|
-
@port = socket.local_address.ip_port
|
63
|
-
socket.close
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
62
|
def wait_for_server
|
68
63
|
loop do
|
69
64
|
begin
|
70
|
-
Net::HTTP.get_response(URI.parse("http://127.0.0.1:#{
|
65
|
+
Net::HTTP.get_response(URI.parse("http://127.0.0.1:#{port}/status"))
|
71
66
|
break
|
72
67
|
rescue
|
73
68
|
end
|
74
69
|
end
|
75
70
|
end
|
76
71
|
|
77
|
-
def with_lock
|
78
|
-
return yield if @config[:lock_file].nil?
|
79
|
-
|
80
|
-
File.open(@config[:lock_file], 'a+') do |file|
|
81
|
-
begin
|
82
|
-
file.flock File::LOCK_EX
|
83
|
-
return yield
|
84
|
-
ensure
|
85
|
-
file.flock File::LOCK_UN
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
72
|
end
|
91
73
|
end
|
data/lib/crabfarm/rspec.rb
CHANGED
@@ -1,26 +1,22 @@
|
|
1
|
-
require 'crabfarm/crabtrap_context'
|
2
|
-
require 'net/http'
|
3
|
-
|
4
|
-
CF_TEST_CONTEXT = Crabfarm::CrabtrapContext::new
|
5
|
-
CF_TEST_CONTEXT.load
|
6
|
-
|
7
1
|
module Crabfarm
|
8
2
|
module RSpec
|
9
3
|
|
10
|
-
|
11
|
-
fixture = Pathname.new(File.join(ENV['SNAPSHOT_DIR'], _snap_or_url))
|
12
|
-
html = if fixture.exist?
|
13
|
-
File.read fixture.realpath
|
14
|
-
else
|
15
|
-
Net::HTTP.get(URI.parse _snap_or_url)
|
16
|
-
end
|
4
|
+
class Error < Crabfarm::Error; end
|
17
5
|
|
6
|
+
def parse(_snapshot, _options={})
|
7
|
+
snapshot_path = GlobalState.snapshot_path _snapshot
|
8
|
+
raise Error.new "Snapshot does not exist #{_snapshot}" unless File.exist? snapshot_path
|
9
|
+
|
10
|
+
html = File.read snapshot_path
|
18
11
|
parser = described_class.new html, _options
|
19
12
|
parser.parse
|
20
13
|
parser
|
21
14
|
end
|
22
15
|
|
23
16
|
def crawl(_state=nil, _params={})
|
17
|
+
|
18
|
+
raise Error.new "Crawl is only available in state specs" if @context.nil?
|
19
|
+
|
24
20
|
if _state.is_a? Hash
|
25
21
|
_params = _state
|
26
22
|
_state = nil
|
@@ -28,9 +24,9 @@ module Crabfarm
|
|
28
24
|
|
29
25
|
if _state.nil?
|
30
26
|
return nil unless described_class < BaseState # TODO: maybe raise an error here.
|
31
|
-
@state = @last_state = TransitionService.apply_state
|
27
|
+
@state = @last_state = TransitionService.apply_state @context, described_class, _params
|
32
28
|
else
|
33
|
-
@last_state = TransitionService.apply_state
|
29
|
+
@last_state = TransitionService.apply_state @context, _state, _params
|
34
30
|
end
|
35
31
|
end
|
36
32
|
|
@@ -46,26 +42,30 @@ module Crabfarm
|
|
46
42
|
@parser
|
47
43
|
end
|
48
44
|
|
45
|
+
def driver(_session_id=nil)
|
46
|
+
@context.pool.driver(_session_id)
|
47
|
+
end
|
48
|
+
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
52
|
RSpec.configure do |config|
|
53
53
|
config.include Crabfarm::RSpec
|
54
54
|
|
55
|
-
config.
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
config.around(:example) do |example|
|
56
|
+
if described_class < Crabfarm::BaseParser
|
57
|
+
if example.metadata[:parsing]
|
58
|
+
@parser = parse example.metadata[:parsing], example.metadata[:using] || {}
|
59
|
+
end
|
60
|
+
example.run
|
61
|
+
elsif described_class < Crabfarm::BaseState
|
62
|
+
Crabfarm::ContextFactory.with_context example.metadata[:crawling] do |ctx|
|
63
|
+
@context = ctx
|
64
|
+
example.run
|
65
|
+
end
|
63
66
|
else
|
64
|
-
|
67
|
+
example.run
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
68
|
-
config.after(:suite) do
|
69
|
-
CF_TEST_CONTEXT.release
|
70
|
-
end
|
71
71
|
end
|
@@ -65,10 +65,13 @@ set_driver :phantomjs
|
|
65
65
|
# set_driver_remote_timeout 120
|
66
66
|
|
67
67
|
|
68
|
-
#
|
68
|
+
# Recording configuration
|
69
69
|
########################################
|
70
70
|
|
71
|
-
# The following parameters only apply when
|
71
|
+
# The following parameters only apply when recording or replaying mementos
|
72
72
|
|
73
73
|
# Set the crabtrap executable location, by default crabfarm expects crabtrap to be included in enviroment
|
74
74
|
# set_crabtrap_bin_path 'crabtrap'
|
75
|
+
|
76
|
+
# Change the browser used for the recording command, available options are 'firefox' or 'chrome'
|
77
|
+
# set_recorder_driver :firefox
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Crabfarm
|
2
|
+
module Utils
|
3
|
+
module PortDiscovery
|
4
|
+
|
5
|
+
def self.find_available_port
|
6
|
+
begin
|
7
|
+
socket = Socket.new(:INET, :STREAM, 0)
|
8
|
+
socket.bind(Addrinfo.tcp("127.0.0.1", 0))
|
9
|
+
return socket.local_address.ip_port
|
10
|
+
ensure
|
11
|
+
socket.close rescue nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/crabfarm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crabfarm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ignacio Baixas
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '2.
|
19
|
+
version: '2.45'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '2.
|
26
|
+
version: '2.45'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: nokogiri
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -377,6 +377,7 @@ files:
|
|
377
377
|
- lib/crabfarm/cli.rb
|
378
378
|
- lib/crabfarm/configuration.rb
|
379
379
|
- lib/crabfarm/context.rb
|
380
|
+
- lib/crabfarm/context_factory.rb
|
380
381
|
- lib/crabfarm/crabtrap_context.rb
|
381
382
|
- lib/crabfarm/crabtrap_runner.rb
|
382
383
|
- lib/crabfarm/default_driver_factory.rb
|
@@ -385,10 +386,11 @@ files:
|
|
385
386
|
- lib/crabfarm/dsl/surfer/search_context.rb
|
386
387
|
- lib/crabfarm/dsl/surfer/surf_context.rb
|
387
388
|
- lib/crabfarm/dsl/surfer.rb
|
388
|
-
- lib/crabfarm/engines/
|
389
|
+
- lib/crabfarm/engines/async_state_manager.rb
|
390
|
+
- lib/crabfarm/engines/sync_state_manager.rb
|
389
391
|
- lib/crabfarm/errors.rb
|
390
|
-
- lib/crabfarm/event_store.rb
|
391
392
|
- lib/crabfarm/forked_state.rb
|
393
|
+
- lib/crabfarm/global_state.rb
|
392
394
|
- lib/crabfarm/http_client.rb
|
393
395
|
- lib/crabfarm/mocks/noop_driver.rb
|
394
396
|
- lib/crabfarm/modes/console.rb
|
@@ -417,6 +419,7 @@ files:
|
|
417
419
|
- lib/crabfarm/templates/state.rb.erb
|
418
420
|
- lib/crabfarm/templates/state_spec.rb.erb
|
419
421
|
- lib/crabfarm/transition_service.rb
|
422
|
+
- lib/crabfarm/utils/port_discovery.rb
|
420
423
|
- lib/crabfarm/version.rb
|
421
424
|
- lib/crabfarm.rb
|
422
425
|
- bin/crabfarm
|
data/lib/crabfarm/event_store.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Crabfarm
|
2
|
-
class EventStore
|
3
|
-
|
4
|
-
def initialize
|
5
|
-
@events = []
|
6
|
-
@mutex = Mutex.new
|
7
|
-
end
|
8
|
-
|
9
|
-
def event(_category, _message)
|
10
|
-
@mutex.synchronize do
|
11
|
-
@events << {
|
12
|
-
created_at: Time.current,
|
13
|
-
category: _category,
|
14
|
-
msg: _message
|
15
|
-
}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|