fbe 0.19.2 → 0.19.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: a2d7532cc824357975d405225601f1f0873721e96b5328a9cd4e1d57191008a9
4
- data.tar.gz: 1c64cade131c3f2751c0dffaaa9bd157cdc4ff41a70b0acf5efe8a8f2788e08b
3
+ metadata.gz: df9755e6d4d7bf5ae3a716031216786929ddfcdf328a3f026b308e9bbfc93f92
4
+ data.tar.gz: ed1cfe9f9877a3e3e1b77f30f4b9c8ca525885306d100058d5397019ca1005e6
5
5
  SHA512:
6
- metadata.gz: 742ec0b8b9970a86549a8292ad5390cb5dcdb4addbc4c45590f3ff10526a67d4038c65cc9534d818859558a0915efeeef30d165816cd24a9a12cda2ec83cc87e
7
- data.tar.gz: 70eb53d6eb30817c735ef3ab2ea62e050106b616a8384a647106c0ef4b40e861deb62d6a3dfc43a32471157144c9225425e092e4a4df614e91679444c5219f64
6
+ metadata.gz: 3bfc015d2f0c47035fae903627404da6fafcd823c14abdcdc8a37694fea73bbb4edd1f1467497379fff51e62388b741a205b28bcd0ee8a4b5c28aceaf0f6c22c
7
+ data.tar.gz: dc92c946e0d1bd14deb3d29a73b36f9317d7e06597ac2ec4fc05030ed9afea415830a71f101eb54ddd2793a02a3c6b480d2a2b95482f3deb0d62903230b1432e
@@ -21,9 +21,6 @@ class Fbe::Middleware::SqliteStore
21
21
  dir = File.dirname(path)
22
22
  raise ArgumentError, "Directory #{dir} does not exist" unless File.directory?(dir)
23
23
  @path = File.absolute_path(path)
24
- open
25
- prepare
26
- at_exit { close }
27
24
  end
28
25
 
29
26
  def read(key)
@@ -37,9 +34,13 @@ class Fbe::Middleware::SqliteStore
37
34
  end
38
35
 
39
36
  def write(key, value)
37
+ return if value.is_a?(Array) && value.any? do |vv|
38
+ req = JSON.parse(vv[0])
39
+ req['url'].include?('?') || req['method'] != 'get'
40
+ end
40
41
  value = JSON.dump(value)
41
- perform do |tdb|
42
- tdb.execute(<<~SQL, [key, value])
42
+ perform do |t|
43
+ t.execute(<<~SQL, [key, value])
43
44
  INSERT INTO cache(key, value) VALUES(?1, ?2)
44
45
  ON CONFLICT(key) DO UPDATE SET value = ?2
45
46
  SQL
@@ -47,32 +48,10 @@ class Fbe::Middleware::SqliteStore
47
48
  nil
48
49
  end
49
50
 
50
- def open
51
- return if @db
52
- @db = SQLite3::Database.new(@path)
53
- end
54
-
55
- def prepare
56
- perform do |tdb|
57
- tdb.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT);'
58
- tdb.execute 'CREATE INDEX IF NOT EXISTS key_idx ON cache(key);'
59
- end
60
- end
61
-
62
- def close
63
- return if !@db || @db.closed?
64
- @db.close
65
- @db = nil
66
- end
67
-
68
51
  def clear
69
52
  perform { _1.execute 'DELETE FROM cache;' }
70
53
  end
71
54
 
72
- def drop
73
- perform { _1.execute 'DROP TABLE IF EXISTS cache;' }
74
- end
75
-
76
55
  def all
77
56
  perform { _1.execute('SELECT key, value FROM cache') }
78
57
  end
@@ -80,6 +59,14 @@ class Fbe::Middleware::SqliteStore
80
59
  private
81
60
 
82
61
  def perform(&)
62
+ @db ||=
63
+ SQLite3::Database.new(@path).tap do |d|
64
+ d.transaction do |t|
65
+ t.execute 'CREATE TABLE IF NOT EXISTS cache(key TEXT UNIQUE NOT NULL, value TEXT);'
66
+ t.execute 'CREATE INDEX IF NOT EXISTS key_idx ON cache(key);'
67
+ end
68
+ at_exit { @db&.close }
69
+ end
83
70
  @db.transaction(&)
84
71
  end
85
72
  end
data/lib/fbe/octo.rb CHANGED
@@ -76,16 +76,24 @@ def Fbe.octo(options: $options, global: $global, loog: $loog)
76
76
  methods: [:get],
77
77
  backoff_factor: 2
78
78
  )
79
- serializer = Marshal
80
79
  if options.sqlite_cache
81
80
  store = Fbe::Middleware::SqliteStore.new(options.sqlite_cache)
82
- serializer = JSON
83
- loog.info("Using HTTP cache in SQLite file: #{store.path}")
81
+ loog.info(
82
+ "Using HTTP cache in SQLite file: #{store.path} (" \
83
+ "#{File.exist?(store.path) ? "#{File.size(store.path)} bytes" : 'file is absent'}" \
84
+ ')'
85
+ )
86
+ builder.use(
87
+ Faraday::HttpCache,
88
+ store:, serializer: JSON, shared_cache: false, logger: Loog::NULL
89
+ )
90
+ else
91
+ loog.info("No HTTP cache in SQLite file, because 'sqlite_cache' option is not provided")
92
+ builder.use(
93
+ Faraday::HttpCache,
94
+ serializer: Marshal, shared_cache: false, logger: Loog::NULL
95
+ )
84
96
  end
85
- builder.use(
86
- Faraday::HttpCache,
87
- store: store, serializer: serializer, shared_cache: false, logger: Loog::NULL
88
- )
89
97
  builder.use(Octokit::Response::RaiseError)
90
98
  builder.use(Faraday::Response::Logger, loog, formatter: Fbe::Middleware::Formatter)
91
99
  builder.use(Fbe::Middleware::Trace, trace)
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.19.2' unless const_defined?(:VERSION)
13
+ VERSION = '0.19.3' unless const_defined?(:VERSION)
14
14
  end
@@ -3,6 +3,7 @@
3
3
  # SPDX-FileCopyrightText: Copyright (c) 2024-2025 Zerocracy
4
4
  # SPDX-License-Identifier: MIT
5
5
 
6
+ require 'qbash'
6
7
  require_relative '../../test__helper'
7
8
  require_relative '../../../lib/fbe/middleware'
8
9
  require_relative '../../../lib/fbe/middleware/sqlite_store'
@@ -12,24 +13,107 @@ require_relative '../../../lib/fbe/middleware/sqlite_store'
12
13
  # Copyright:: Copyright (c) 2024-2025 Zerocracy
13
14
  # License:: MIT
14
15
  class SqliteStoreTest < Fbe::Test
15
- def test_sqlite_store
16
- Dir.mktmpdir do |dir|
17
- store = Fbe::Middleware::SqliteStore.new(File.expand_path('test.db', dir))
18
- assert_nil(store.read('my_key'))
19
- assert_nil(store.delete('my_key'))
20
- assert_nil(store.write('my_key', 'some value'))
21
- assert_equal('some value', store.read('my_key'))
22
- assert_nil(store.write('my_key', 'some value 2'))
23
- assert_equal('some value 2', store.read('my_key'))
24
- assert_nil(store.delete('my_key'))
25
- assert_nil(store.read('my_key'))
16
+ def test_simple_caching_algorithm
17
+ with_tmpfile('x.db') do |f|
18
+ store = Fbe::Middleware::SqliteStore.new(f)
19
+ k = 'some-key'
20
+ assert_nil(store.read(k))
21
+ assert_nil(store.delete(k))
22
+ v1 = 'first value to save'
23
+ assert_nil(store.write(k, v1))
24
+ assert_equal(v1, store.read(k))
25
+ v2 = 'another value to save'
26
+ assert_nil(store.write(k, v2))
27
+ assert_equal(v2, store.read(k))
28
+ assert_nil(store.delete(k))
29
+ assert_nil(store.read(k))
30
+ assert_path_exists(f)
26
31
  end
27
32
  end
28
33
 
29
- def test_sqlite_store_empty_all
30
- Dir.mktmpdir do |dir|
31
- store = Fbe::Middleware::SqliteStore.new(File.expand_path('test.db', dir))
34
+ def test_returns_empty_list
35
+ with_tmpfile('b.db') do |f|
36
+ store = Fbe::Middleware::SqliteStore.new(f)
37
+ assert_empty(store.all)
38
+ end
39
+ end
40
+
41
+ def test_clear_all_keys
42
+ with_tmpfile('a.db') do |f|
43
+ store = Fbe::Middleware::SqliteStore.new(f)
44
+ k = 'a key'
45
+ store.write(k, 'some value')
46
+ store.clear
47
+ assert_empty(store.all)
48
+ end
49
+ end
50
+
51
+ def test_empty_all_if_not_written
52
+ with_tmpfile do |f|
53
+ store = Fbe::Middleware::SqliteStore.new(f)
32
54
  assert_empty(store.all)
33
55
  end
34
56
  end
57
+
58
+ def test_wrong_db_path
59
+ assert_raises(ArgumentError) do
60
+ Fbe::Middleware::SqliteStore.new(nil).read('my_key')
61
+ end
62
+ assert_raises(ArgumentError) do
63
+ Fbe::Middleware::SqliteStore.new('').read('my_key')
64
+ end
65
+ assert_raises(ArgumentError) do
66
+ Fbe::Middleware::SqliteStore.new('/fakepath/fakefolder/test.db').read('my_key')
67
+ end
68
+ end
69
+
70
+ def test_not_db_file
71
+ with_tmpfile do |f|
72
+ File.binwrite(f, Array.new(20) { rand(0..255) }.pack('C*'))
73
+ ex =
74
+ assert_raises(SQLite3::NotADatabaseException) do
75
+ Fbe::Middleware::SqliteStore.new(f).read('my_key')
76
+ end
77
+ assert_match('file is not a database', ex.message)
78
+ end
79
+ end
80
+
81
+ def test_defer_db_close_callback
82
+ txt = <<~RUBY
83
+ require 'tempfile'
84
+ require 'sqlite3'
85
+ require 'fbe/middleware/sqlite_store'
86
+
87
+ SQLite3::Database.class_eval do
88
+ prepend(Module.new do
89
+ def close
90
+ super
91
+ puts 'closed sqlite after process exit'
92
+ end
93
+ end)
94
+ end
95
+
96
+ Tempfile.open('test.db') do |f|
97
+ Fbe::Middleware::SqliteStore.new(f.path).then do |s|
98
+ s.write('my_key', 'my_value')
99
+ s.read('my_key')
100
+ end
101
+ end
102
+ RUBY
103
+ out =
104
+ qbash(
105
+ 'bundle exec ruby ' \
106
+ "-I#{Shellwords.escape(File.expand_path('../../../lib', __dir__))} " \
107
+ "-e #{Shellwords.escape(txt)} 2>&1"
108
+ )
109
+ assert_match('closed sqlite after process exit', out)
110
+ end
111
+
112
+ private
113
+
114
+ def with_tmpfile(name = 'test.db', &)
115
+ Dir.mktmpdir do |dir|
116
+ yield File.expand_path(name, dir)
117
+ end
118
+ end
35
119
  end
@@ -256,7 +256,10 @@ class TestOcto < Fbe::Test
256
256
  end
257
257
 
258
258
  def test_reads_quota
259
- WebMock.enable_net_connect!
259
+ WebMock.disable_net_connect!
260
+ stub_request(:get, 'https://api.github.com/rate_limit').to_return(
261
+ { body: '{}', headers: { 'X-RateLimit-Remaining' => '222' } }
262
+ )
260
263
  o = Fbe.octo(loog: Loog::VERBOSE, global: {}, options: Judges::Options.new({ 'github_api_pause' => 0.01 }))
261
264
  refute_nil(o.off_quota?)
262
265
  end
@@ -365,7 +368,7 @@ class TestOcto < Fbe::Test
365
368
  assert_includes second_output, 'GitHub API trace is empty'
366
369
  end
367
370
 
368
- def test_sqlite_store
371
+ def test_works_via_sqlite_store
369
372
  WebMock.disable_net_connect!
370
373
  Dir.mktmpdir do |dir|
371
374
  global = {}
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.19.2
4
+ version: 0.19.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko