ask-web-fetch 0.5.2 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18e8a7b0274def2380d5b75df069e428aeca9e027352f2fc09ee64b65d946a68
4
- data.tar.gz: d69e005edde7afcf8b05a8d89da9655be939ab7e21b039d6d61c617b4a1d74de
3
+ metadata.gz: ed798fddd5578a39814ea41425937d4e539827dae6c66a8e9bc1621007f5dcda
4
+ data.tar.gz: 698add682f0ce4f056acfee23130748bb6d359acb8004a07efc6b862dcc462da
5
5
  SHA512:
6
- metadata.gz: 0e7c44e68630b3b7c2e7a5c04581b2e9992a888c927ecb5de47b4782f92538fa0e5b71eb53ea4fea325c6f354595338698abfac5540260e09d162d30673db347
7
- data.tar.gz: 6f67717fbe1aeec17b0cfbc4939c3b9195ebd229976ca744ebe8ef67de08e9bae6630ca8fbd2fa7b50979487ce331d8a2edaf96e12818185d2ea855ed295c477
6
+ metadata.gz: 0aa82e97aef13e08d736024d4927a96a72a554ec1cda21292d501884787ad82e756c51522a179ebfd81bdbcd5baadef6965254957613044e088e511accdfb4f1
7
+ data.tar.gz: e5d46eef13701008e7c4557675d372b6c4776f38f19b75be4559943b675def5d9370006cb9ef10416a7b70f6a3897f54b7c14f4afff409afd590dee0fa068ac7
@@ -50,6 +50,9 @@ module Ask
50
50
  @session = @client.session(
51
51
  @client.command('Target.attachToTarget', targetId: @target_id, flatten: true)['sessionId']
52
52
  )
53
+ # Subscribed BEFORE any navigation so the idle wait sees the
54
+ # page's real load traffic (lazy SPAs render in waves).
55
+ @network = Network.new(self)
53
56
  end
54
57
 
55
58
  # Navigates and does not return until the document has actually
@@ -65,7 +68,6 @@ module Ask
65
68
 
66
69
  wait_for_load
67
70
  end
68
-
69
71
  def title
70
72
  evaluate('document.title')
71
73
  end
@@ -78,11 +80,11 @@ module Ask
78
80
  evaluate('document.documentElement.outerHTML') || ''
79
81
  end
80
82
 
81
- # Minimal network facade for the Browser backend. The status comes
82
- # from the Navigation Timing API (the main document's HTTP status);
83
- # attached pages need no idle wait — they only exist once loaded.
83
+ # Minimal network facade for the Browser backend: status from the
84
+ # Navigation Timing API, idle from CDP Network events (subscribed
85
+ # in the constructor, before navigation).
84
86
  def network
85
- @network ||= Network.new(self)
87
+ @network
86
88
  end
87
89
 
88
90
  def close
@@ -122,10 +124,22 @@ module Ask
122
124
  nil
123
125
  end
124
126
 
125
- # Status + no-op idle for the Browser backend's fetch flow.
127
+ # Real network-idle detection for the attached browser, via CDP's
128
+ # Network domain events. The launched-browser path gets idle
129
+ # waiting from Ferrum's network; the attached path previously
130
+ # skipped it entirely (a no-op), which read lazy-loading SPAs too
131
+ # early — reddit's post list renders in waves, and the fetch saw
132
+ # only the first 2.6k of an 8k+ body. Tracks requestStarted /
133
+ # requestFinished events on the page session and waits until the
134
+ # network has been quiet for +duration+, capped at +timeout+.
126
135
  class Network
127
136
  def initialize(page)
128
137
  @page = page
138
+ @session = page.instance_variable_get(:@session)
139
+ @in_flight = 0
140
+ @quiet_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
141
+ @mutex = Mutex.new
142
+ subscribe
129
143
  end
130
144
 
131
145
  def status
@@ -137,7 +151,39 @@ module Ask
137
151
  0
138
152
  end
139
153
 
140
- def wait_for_idle(*)
154
+ def wait_for_idle(duration:, timeout:)
155
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
156
+ loop do
157
+ quiet = @mutex.synchronize { @in_flight.zero? }
158
+ if quiet && Process.clock_gettime(Process::CLOCK_MONOTONIC) - @quiet_since >= duration
159
+ return
160
+ end
161
+ raise Ferrum::TimeoutError, "network did not go idle within #{timeout}s" if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
162
+
163
+ sleep 0.1
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ # CDP events arrive on the session's message loop; Ferrum's
170
+ # session dispatches them to subscribed handlers. Track the
171
+ # request lifecycle so "quiet" means no request has been in
172
+ # flight for the duration — the signal lazy SPAs settle on.
173
+ # Defensive: a minimal/mock session without event support
174
+ # (some test doubles) just skips subscription — the load-wait
175
+ # in go_to is still the floor.
176
+ def subscribe
177
+ return unless @session.respond_to?(:on)
178
+
179
+ @session.on('Network.requestWillBeSent') { @mutex.synchronize { @in_flight += 1 } }
180
+ @session.on('Network.responseReceived') { @mutex.synchronize { @quiet_since = Process.clock_gettime(Process::CLOCK_MONOTONIC) } }
181
+ @session.on('Network.loadingFinished') { @mutex.synchronize { @in_flight -= 1 if @in_flight.positive? } }
182
+ @session.on('Network.loadingFailed') { @mutex.synchronize { @in_flight -= 1 if @in_flight.positive? } }
183
+ @session.command('Network.enable')
184
+ rescue Ferrum::Error
185
+ # Some attached browsers reject Network.enable (unlikely);
186
+ # fall back to the load-wait already done in go_to.
141
187
  nil
142
188
  end
143
189
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module WebFetch
5
- VERSION = '0.5.2'
5
+ VERSION = '0.5.3'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-web-fetch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto