fbe 0.31.2 → 0.33.0

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: 3a677f7f6496d3ae71e301f9f495b4907391bbde215407b702a8fbb956912935
4
- data.tar.gz: 2afe6bbef989ffc24291cf00db87f917513469f0ae2a99ecbac4429692dbf479
3
+ metadata.gz: '05709f3a8b84855b1cb59a586eb4ae7a83f2f87bf0d8490d14a4b59659513cd6'
4
+ data.tar.gz: 54da9a5a7e9d638859cfdb0b7c9b192673fdb2ede19ae4e3afecdbcf1164db36
5
5
  SHA512:
6
- metadata.gz: ed332e9aece1b31c3cc25716dd16dea036ebffa048caaaa8028b84a91702852d146910e46b1dfb731e7cbf9d6af54f8b0fd1409e282f61be5fd2398935cb4581
7
- data.tar.gz: c0edfee023e86ccc3a669111b7c68492d35d030d2d1e31f0262059f91e12839709b0f73f15a14b7b3755347b44fa3b5e157754c6babbec7dee2c2ee33ae120f9
6
+ metadata.gz: ab66f21e8f0f80070e3a8908fade06c2088659660d6d9aa127f6bc86e555b3efc4d3542aae40cfd301e2caa0af80a9227b02aaac5ce7e562ec346dad85d06ecf
7
+ data.tar.gz: e381efafdacff36bf1119f0075c18f558af4531a17a4e2ad9d15663f330bca2da7cde3c0862d2d98db5ee6bbe28e12d41c8617bd923b334c5b833befbfe8dcbb
data/Gemfile.lock CHANGED
@@ -60,7 +60,7 @@ GEM
60
60
  tago (~> 0.0)
61
61
  typhoeus (~> 1.4)
62
62
  benchmark (0.4.1)
63
- bigdecimal (3.2.2)
63
+ bigdecimal (3.2.3)
64
64
  builder (3.3.0)
65
65
  concurrent-ruby (1.3.5)
66
66
  connection_pool (2.5.4)
@@ -76,7 +76,7 @@ GEM
76
76
  ellipsized (0.3.0)
77
77
  ethon (0.15.0)
78
78
  ffi (>= 1.15.0)
79
- factbase (0.15.7)
79
+ factbase (0.16.1)
80
80
  backtrace (~> 0.4)
81
81
  decoor (~> 0.1)
82
82
  ellipsized (~> 0.3)
@@ -114,7 +114,7 @@ GEM
114
114
  graphql-client (0.26.0)
115
115
  activesupport (>= 3.0)
116
116
  graphql (>= 1.13.0)
117
- hashdiff (1.2.0)
117
+ hashdiff (1.2.1)
118
118
  i18n (1.14.7)
119
119
  concurrent-ruby (~> 1.0)
120
120
  intercepted (0.2.0)
@@ -207,10 +207,10 @@ GEM
207
207
  lint_roller (~> 1.1)
208
208
  rubocop (>= 1.75.0, < 2.0)
209
209
  rubocop-ast (>= 1.38.0, < 2.0)
210
- rubocop-performance (1.25.0)
210
+ rubocop-performance (1.26.0)
211
211
  lint_roller (~> 1.1)
212
212
  rubocop (>= 1.75.0, < 2.0)
213
- rubocop-ast (>= 1.38.0, < 2.0)
213
+ rubocop-ast (>= 1.44.0, < 2.0)
214
214
  rubocop-rake (0.7.1)
215
215
  lint_roller (~> 1.1)
216
216
  rubocop (>= 1.72.1)
@@ -233,7 +233,7 @@ GEM
233
233
  sqlite3 (2.7.3-x86_64-darwin)
234
234
  sqlite3 (2.7.3-x86_64-linux-gnu)
235
235
  strscan (3.1.5)
236
- tago (0.1.0)
236
+ tago (0.2.0)
237
237
  timeout (0.4.3)
238
238
  total (0.4.1)
239
239
  typhoeus (1.5.0)
data/lib/fbe/conclude.rb CHANGED
@@ -19,14 +19,14 @@ require_relative 'octo'
19
19
  # @yield [Factbase::Fact] The fact
20
20
  def Fbe.conclude(
21
21
  fb: Fbe.fb, judge: $judge, loog: $loog, options: $options, global: $global,
22
- start: $start, time: Time, &
22
+ start: $start, &
23
23
  )
24
24
  raise 'The fb is nil' if fb.nil?
25
25
  raise 'The $judge is not set' if judge.nil?
26
26
  raise 'The $global is not set' if global.nil?
27
27
  raise 'The $options is not set' if options.nil?
28
28
  raise 'The $loog is not set' if loog.nil?
29
- c = Fbe::Conclude.new(fb:, judge:, loog:, options:, global:, start:, time:)
29
+ c = Fbe::Conclude.new(fb:, judge:, loog:, options:, global:, start:)
30
30
  c.instance_eval(&)
31
31
  end
32
32
 
@@ -61,8 +61,7 @@ class Fbe::Conclude
61
61
  # @param [Hash] global The hash for global caching
62
62
  # @param [Judges::Options] options The options coming from the +judges+ tool
63
63
  # @param [Loog] loog The logging facility
64
- # @param [Time] time The time
65
- def initialize(fb:, judge:, global:, options:, loog:, start:, time: Time)
64
+ def initialize(fb:, judge:, global:, options:, loog:, start:)
66
65
  @fb = fb
67
66
  @judge = judge
68
67
  @loog = loog
@@ -74,7 +73,6 @@ class Fbe::Conclude
74
73
  @lifetime_aware = true
75
74
  @quota_aware = true
76
75
  @timeout = 60
77
- @time = time
78
76
  end
79
77
 
80
78
  # Make this block not aware of GitHub API quota.
@@ -92,7 +90,7 @@ class Fbe::Conclude
92
90
  # When the lifetime is over, the loop will NOT gracefully stop.
93
91
  #
94
92
  # @return [nil] Nothing is returned
95
- def lifetime_aware
93
+ def lifetime_unaware
96
94
  @lifetime_aware = false
97
95
  end
98
96
 
@@ -195,7 +193,6 @@ class Fbe::Conclude
195
193
  # end
196
194
  def roll(&)
197
195
  passed = 0
198
- start = @time.now
199
196
  oct = Fbe.octo(loog: @loog, options: @options, global: @global)
200
197
  @fb.query(@query).each do |a|
201
198
  if @quota_aware && oct.off_quota?
@@ -206,9 +203,8 @@ class Fbe::Conclude
206
203
  @loog.debug('We ran out of lifetime, must stop here')
207
204
  break
208
205
  end
209
- now = @time.now
210
- if now > start + @timeout
211
- @loog.debug("We've spent more than #{start.ago}, must stop here")
206
+ if Time.now > @start + @timeout
207
+ @loog.debug("We've spent more than #{@start.ago}, must stop here")
212
208
  break
213
209
  end
214
210
  @fb.txn do |fbt|
data/lib/fbe/iterate.rb CHANGED
@@ -8,7 +8,9 @@ require 'tago'
8
8
  require 'time'
9
9
  require_relative '../fbe'
10
10
  require_relative 'fb'
11
+ require_relative 'if_absent'
11
12
  require_relative 'octo'
13
+ require_relative 'overwrite'
12
14
  require_relative 'unmask_repos'
13
15
 
14
16
  # Creates an instance of {Fbe::Iterate} and evaluates it with the provided block.
@@ -26,7 +28,7 @@ require_relative 'unmask_repos'
26
28
  # @raise [RuntimeError] If required globals are not set
27
29
  # @example Iterate through repositories processing issues
28
30
  # Fbe.iterate do
29
- # as 'issues-iterator'
31
+ # as 'issues_iterator'
30
32
  # by '(and (eq what "issue") (gt created_at $before))'
31
33
  # repeats 5
32
34
  # quota_aware
@@ -35,12 +37,12 @@ require_relative 'unmask_repos'
35
37
  # issue_id + 1
36
38
  # end
37
39
  # end
38
- def Fbe.iterate(fb: Fbe.fb, loog: $loog, options: $options, global: $global, &)
40
+ def Fbe.iterate(fb: Fbe.fb, loog: $loog, options: $options, global: $global, start: $start, &)
39
41
  raise 'The fb is nil' if fb.nil?
40
42
  raise 'The $global is not set' if global.nil?
41
43
  raise 'The $options is not set' if options.nil?
42
44
  raise 'The $loog is not set' if loog.nil?
43
- c = Fbe::Iterate.new(fb:, loog:, options:, global:)
45
+ c = Fbe::Iterate.new(fb:, loog:, options:, global:, start:)
44
46
  c.instance_eval(&)
45
47
  end
46
48
 
@@ -62,7 +64,7 @@ end
62
64
  #
63
65
  # @example Processing pull requests with state management
64
66
  # iterator = Fbe::Iterate.new(fb: fb, loog: loog, options: options, global: global)
65
- # iterator.as('pull-requests')
67
+ # iterator.as('pull_requests')
66
68
  # iterator.by('(and (eq what "pull_request") (gt number $before))')
67
69
  # iterator.repeats(10)
68
70
  # iterator.quota_aware
@@ -82,16 +84,18 @@ class Fbe::Iterate
82
84
  # @param [Loog] loog The logging facility for debug output
83
85
  # @param [Judges::Options] options The options containing repository configuration
84
86
  # @param [Hash] global The hash for global caching of API responses
85
- def initialize(fb:, loog:, options:, global:)
87
+ def initialize(fb:, loog:, options:, global:, start:)
86
88
  @fb = fb
87
89
  @loog = loog
88
90
  @options = options
89
91
  @global = global
92
+ @start = start
90
93
  @label = nil
91
94
  @since = 0
92
95
  @query = nil
93
96
  @repeats = 1
94
- @quota_aware = false
97
+ @quota_aware = true
98
+ @lifetime_aware = true
95
99
  end
96
100
 
97
101
  # Makes the iterator aware of GitHub API quota limits.
@@ -104,8 +108,15 @@ class Fbe::Iterate
104
108
  # @example Enable quota awareness
105
109
  # iterator.quota_aware
106
110
  # iterator.over { |repo, item| ... } # Will stop if quota exhausted
107
- def quota_aware
108
- @quota_aware = true
111
+ def quota_unaware
112
+ @quota_aware = false
113
+ end
114
+
115
+ # Makes the iterator aware of lifetime limits.
116
+ #
117
+ # @return [nil] Nothing is returned
118
+ def lifetime_unaware
119
+ @lifetime_aware = false
109
120
  end
110
121
 
111
122
  # Sets the maximum number of iterations per repository.
@@ -151,10 +162,11 @@ class Fbe::Iterate
151
162
  # @return [nil] Nothing is returned
152
163
  # @raise [RuntimeError] If label is already set or nil
153
164
  # @example Set label for issue processing
154
- # iterator.as('issue-processor')
165
+ # iterator.as('issue_processor')
155
166
  def as(label)
156
167
  raise 'Label is already set' unless @label.nil?
157
168
  raise 'Cannot set "label" to nil' if label.nil?
169
+ raise "Wrong label format '#{label}', use [_a-z][a-zA-Z0-9_]*" unless label.match?(/\A[_a-z][a-zA-Z0-9_]*\z/)
158
170
  @label = label
159
171
  end
160
172
 
@@ -185,7 +197,6 @@ class Fbe::Iterate
185
197
  # 4. If query returns a value: call the block with (repo_id, query_result)
186
198
  # 5. Store the block's return value as the new "latest" for next iteration
187
199
  #
188
- # @param [Float] timeout Maximum seconds to run (default: 120)
189
200
  # @yield [Integer, Object] Repository ID and the result from query execution
190
201
  # @yieldreturn [Integer] The value to store as "latest" for next iteration
191
202
  # @return [nil] Nothing is returned
@@ -195,7 +206,7 @@ class Fbe::Iterate
195
206
  # fetch_and_process_issue(repo_id, issue_number)
196
207
  # issue_number + 1 # Return next issue number to process
197
208
  # end
198
- def over(timeout: 2 * 60, &)
209
+ def over
199
210
  raise 'Use "as" first' if @label.nil?
200
211
  raise 'Use "by" first' if @query.nil?
201
212
  seen = {}
@@ -208,27 +219,27 @@ class Fbe::Iterate
208
219
  loog: @loog, options: @options, global: @global, quota_aware: @quota_aware
209
220
  ).map { |n| oct.repo_id_by_name(n) }
210
221
  restarted = []
211
- start = Time.now
222
+ started = Time.now
212
223
  before =
213
224
  repos.to_h do |repo|
214
225
  [
215
226
  repo,
216
227
  @fb.query(
217
228
  "(agg (and
218
- (eq what '#{@label}')
229
+ (eq what 'iterate')
219
230
  (eq where 'github')
220
231
  (eq repository #{repo}))
221
- (first latest))"
232
+ (first #{@label}))"
222
233
  ).one&.first || @since
223
234
  ]
224
235
  end
225
236
  starts = before.dup
226
237
  loop do
227
238
  if @quota_aware && oct.off_quota?
228
- @loog.info("We are off GitHub quota, time to stop after #{start.ago}")
239
+ @loog.info("We are off GitHub quota, time to stop after #{started.ago}")
229
240
  break
230
241
  end
231
- if Time.now - start > timeout
242
+ if @lifetime_aware && @options.lifetime && Time.now - @start > @options.lifetime - 10
232
243
  @loog.info('We are over time, it is time to stop')
233
244
  break
234
245
  end
@@ -237,8 +248,8 @@ class Fbe::Iterate
237
248
  @loog.info("We are off GitHub quota, we must skip #{repo}")
238
249
  break
239
250
  end
240
- if Time.now - start > timeout
241
- @loog.info("We are doing this for #{start.ago} already, won't check #{repo}")
251
+ if @lifetime_aware && @options.lifetime && Time.now - @start > @options.lifetime - 10
252
+ @loog.info("We are working for #{started.ago} already, won't check repository ##{repo}")
242
253
  next
243
254
  end
244
255
  next if restarted.include?(repo)
@@ -263,28 +274,24 @@ class Fbe::Iterate
263
274
  seen[repo] += 1
264
275
  end
265
276
  unless seen.any? { |r, v| v < @repeats && !restarted.include?(r) }
266
- @loog.debug("No more repos to scan (out of #{repos.size}), quitting after #{start.ago}")
277
+ @loog.debug("No more repos to scan (out of #{repos.size}), quitting after #{started.ago}")
267
278
  break
268
279
  end
269
280
  if restarted.size == repos.size
270
- @loog.debug("All #{repos.size} repos restarted, quitting after #{start.ago}")
281
+ @loog.debug("All #{repos.size} repos restarted, quitting after #{started.ago}")
271
282
  break
272
283
  end
273
284
  end
274
285
  repos.each do |repo|
275
286
  next if before[repo] == starts[repo]
276
- @fb.query(
277
- "(and
278
- (eq what '#{@label}')
279
- (eq where 'github')
280
- (eq repository #{repo}))"
281
- ).delete!
282
- f = @fb.insert
283
- f.where = 'github'
284
- f.repository = repo
285
- f.latest = before[repo]
286
- f.what = @label
287
+ f =
288
+ Fbe.if_absent(fb: @fb, always: true) do |n|
289
+ n.what = 'iterate'
290
+ n.where = 'github'
291
+ n.repository = repo
292
+ end
293
+ Fbe.overwrite(f, @label, before[repo], fb: @fb)
287
294
  end
288
- @loog.debug("Finished scanning #{repos.size} repos in #{start.ago}: #{seen.map { |k, v| "#{k}:#{v}" }.joined}")
295
+ @loog.debug("Finished scanning #{repos.size} repos in #{started.ago}: #{seen.map { |k, v| "#{k}:#{v}" }.joined}")
289
296
  end
290
297
  end
data/lib/fbe/tombstone.rb CHANGED
@@ -34,7 +34,7 @@ class Fbe::Tombstone
34
34
  n.repo = repo
35
35
  end
36
36
  f.send(:"#{@fid}=", SecureRandom.random_number(99_999)) if f[@fid].nil?
37
- nn = f['issues']&.map { |ii| ii.split('-').map(&:to_i) } || []
37
+ nn = f['issues']&.map { |ii| ii.split('-').map(&:to_i).then { |ii| ii.size == 1 ? ii << ii[0] : ii } } || []
38
38
  issue = [issue] unless issue.is_a?(Array)
39
39
  issue.each do |i|
40
40
  nn << [i, i]
@@ -47,7 +47,9 @@ class Fbe::Tombstone
47
47
  merged << [a, b]
48
48
  end
49
49
  end
50
- Fbe.overwrite(f, 'issues', merged.map { |ii| "#{ii[0]}-#{ii[1]}" }, fb: @fb, fid: @fid)
50
+ Fbe.overwrite(
51
+ f, 'issues', merged.map { |ii| ii[0] == ii[1] ? ii[0].to_s : "#{ii[0]}-#{ii[1]}" }, fb: @fb, fid: @fid
52
+ )
51
53
  end
52
54
 
53
55
  # Is it there?
@@ -64,7 +66,7 @@ class Fbe::Tombstone
64
66
  issue.all? do |i|
65
67
  f['issues'].any? do |ii|
66
68
  a, b = ii.split('-').map(&:to_i)
67
- (a..b).cover?(i)
69
+ b.nil? ? a == i : (a..b).cover?(i)
68
70
  end
69
71
  end
70
72
  end
data/lib/fbe.rb CHANGED
@@ -10,5 +10,5 @@
10
10
  # License:: MIT
11
11
  module Fbe
12
12
  # Current version of the gem (changed by +.rultor.yml+ on every release)
13
- VERSION = '0.31.2' unless const_defined?(:VERSION)
13
+ VERSION = '0.33.0' unless const_defined?(:VERSION)
14
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.31.2
4
+ version: 0.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko