Skip to content

Commit a36eea6

Browse files
authored
Merge pull request #21413 from hyuraku/cache_store-typed-strict
cache_store: `typed: strict`
2 parents 490a3b4 + a65a407 commit a36eea6

File tree

1 file changed

+49
-17
lines changed

1 file changed

+49
-17
lines changed

Library/Homebrew/cache_store.rb

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# typed: true # rubocop:todo Sorbet/StrictSigil
1+
# typed: strict
22
# frozen_string_literal: true
33

44
require "json"
@@ -13,8 +13,16 @@ class CacheStoreDatabase
1313
#
1414
# @param [Symbol] type
1515
# @yield [CacheStoreDatabase] self
16-
def self.use(type)
17-
@db_type_reference_hash ||= {}
16+
sig {
17+
type_parameters(:U)
18+
.params(
19+
type: Symbol,
20+
_blk: T.proc.params(arg0: CacheStoreDatabase).returns(T.type_parameter(:U)),
21+
)
22+
.returns(T.type_parameter(:U))
23+
}
24+
def self.use(type, &_blk)
25+
@db_type_reference_hash ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
1826
@db_type_reference_hash[type] ||= {}
1927
type_ref = @db_type_reference_hash[type]
2028

@@ -42,25 +50,29 @@ def self.use(type)
4250
#
4351
# @param [Symbol] type
4452
# @return [nil]
53+
sig { params(type: Symbol).void }
4554
def initialize(type)
46-
@type = type
47-
@dirty = false
55+
@type = T.let(type, Symbol)
56+
@dirty = T.let(false, T.nilable(T::Boolean))
4857
end
4958

5059
# Sets a value in the underlying database (and creates it if necessary).
60+
sig { params(key: T.anything, value: T.anything).void }
5161
def set(key, value)
5262
dirty!
5363
db[key] = value
5464
end
5565

5666
# Gets a value from the underlying database (if it already exists).
67+
sig { params(key: T.anything).returns(T.untyped) }
5768
def get(key)
5869
return unless created?
5970

6071
db[key]
6172
end
6273

6374
# Deletes a value from the underlying database (if it already exists).
75+
sig { params(key: T.anything).void }
6476
def delete(key)
6577
return unless created?
6678

@@ -69,6 +81,7 @@ def delete(key)
6981
end
7082

7183
# Deletes all content from the underlying database (if it already exists).
84+
sig { void }
7285
def clear!
7386
return unless created?
7487

@@ -77,6 +90,7 @@ def clear!
7790
end
7891

7992
# Closes the underlying database (if it is created and open).
93+
sig { void }
8094
def write_if_dirty!
8195
return unless dirty?
8296

@@ -87,13 +101,15 @@ def write_if_dirty!
87101
# Returns `true` if the cache file has been created for the given `@type`.
88102
#
89103
# @return [Boolean]
104+
sig { returns(T::Boolean) }
90105
def created?
91106
cache_path.exist?
92107
end
93108

94109
# Returns the modification time of the cache file (if it already exists).
95110
#
96111
# @return [Time]
112+
sig { returns(T.nilable(Time)) }
97113
def mtime
98114
return unless created?
99115

@@ -102,21 +118,24 @@ def mtime
102118

103119
# Performs a `select` on the underlying database.
104120
#
105-
# @return [Array]
121+
# @return [Hash]
122+
sig { params(block: T.proc.params(arg0: T.untyped, arg1: T.untyped).returns(BasicObject)).returns(T::Hash[T.untyped, T.untyped]) }
106123
def select(&block)
107124
db.select(&block)
108125
end
109126

110127
# Returns `true` if the cache is empty.
111128
#
112129
# @return [Boolean]
130+
sig { returns(T::Boolean) }
113131
def empty?
114132
db.empty?
115133
end
116134

117135
# Performs a `each_key` on the underlying database.
118136
#
119-
# @return [Array]
137+
# @return [Hash]
138+
sig { params(block: T.proc.params(arg0: T.untyped).returns(BasicObject)).returns(T::Hash[T.untyped, T.untyped]) }
120139
def each_key(&block)
121140
db.each_key(&block)
122141
end
@@ -128,33 +147,41 @@ def each_key(&block)
128147
# corresponding to the `@type` instance variable.
129148
#
130149
# @return [Hash] db
150+
sig { returns(T::Hash[T.untyped, T.untyped]) }
131151
def db
132-
@db ||= begin
133-
JSON.parse(cache_path.read) if created?
152+
@db ||= T.let({}, T.nilable(T::Hash[T.untyped, T.untyped]))
153+
return @db if !@db.empty? || !created?
154+
155+
begin
156+
result = JSON.parse(cache_path.read)
157+
@db = result if result.is_a?(Hash)
134158
rescue JSON::ParserError
135-
nil
159+
# Ignore parse errors
136160
end
137-
@db ||= {}
161+
@db
138162
end
139163

140164
# The path where the database resides in the `HOMEBREW_CACHE` for the given
141165
# `@type`.
142166
#
143-
# @return [String]
167+
# @return [Pathname]
168+
sig { returns(Pathname) }
144169
def cache_path
145170
HOMEBREW_CACHE/"#{@type}.json"
146171
end
147172

148173
# Sets that the cache needs to be written to disk.
174+
sig { void }
149175
def dirty!
150176
@dirty = true
151177
end
152178

153179
# Returns `true` if the cache needs to be written to disk.
154180
#
155181
# @return [Boolean]
182+
sig { returns(T::Boolean) }
156183
def dirty?
157-
@dirty
184+
!!@dirty
158185
end
159186
end
160187

@@ -165,34 +192,39 @@ def dirty?
165192
class CacheStore
166193
# @param [CacheStoreDatabase] database
167194
# @return [nil]
195+
sig { params(database: CacheStoreDatabase).void }
168196
def initialize(database)
169-
@database = database
197+
@database = T.let(database, CacheStoreDatabase)
170198
end
171199

172200
# Inserts new values or updates existing cached values to persistent storage.
173201
#
174202
# @abstract
175-
def update!(*)
203+
sig { params(args: T.anything).void }
204+
def update!(*args)
176205
raise NotImplementedError
177206
end
178207

179208
# Fetches cached values in persistent storage according to the type of data
180209
# stored.
181210
#
182211
# @abstract
183-
def fetch(*)
212+
sig { params(args: T.anything).returns(T.untyped) }
213+
def fetch(*args)
184214
raise NotImplementedError
185215
end
186216

187217
# Deletes data from the cache based on a condition defined in a concrete class.
188218
#
189219
# @abstract
190-
def delete!(*)
220+
sig { params(args: T.anything).void }
221+
def delete!(*args)
191222
raise NotImplementedError
192223
end
193224

194225
protected
195226

196227
# @return [CacheStoreDatabase]
228+
sig { returns(CacheStoreDatabase) }
197229
attr_reader :database
198230
end

0 commit comments

Comments
 (0)