@@ -61,7 +61,11 @@ internal struct StoreContext {
6161 else {
6262 let cache = makeNewCache ( of: atom, for: key, override: override)
6363 notifyUpdateToObservers ( )
64- checkRelease ( for: key)
64+
65+ if checkRelease ( for: key) {
66+ notifyUpdateToObservers ( )
67+ }
68+
6569 return cache. value
6670 }
6771 }
@@ -127,19 +131,14 @@ internal struct StoreContext {
127131 location: container. location,
128132 requiresObjectUpdate: requiresObjectUpdate,
129133 notifyUpdate: notifyUpdate
130- ) {
131- let store = getStore ( )
132- // Unsubscribe and release if it's no longer used.
133- store. state. subscriptions [ key] ? . removeValue ( forKey: container. key)
134-
135- if !checkRelease( for: key) {
136- notifyUpdateToObservers ( )
137- }
138- }
134+ )
139135 let isInserted = store. state. subscriptions [ key, default: [ : ] ] . updateValue ( subscription, forKey: container. key) == nil
140136
141137 // Register the subscription to both the store and the container.
142138 container. subscriptions [ key] = subscription
139+ container. unsubscribe = { keys in
140+ unsubscribe ( keys, for: container. key)
141+ }
143142
144143 if isInserted || cache == nil {
145144 notifyUpdateToObservers ( )
@@ -165,8 +164,11 @@ internal struct StoreContext {
165164 if let cache = lookupCache ( of: atom, for: key) {
166165 update ( atom: atom, for: key, value: value, cache: cache, order: . newValue)
167166 }
167+ else {
168+ // Do not notify update observers here because refresh doesn't create a new cache.
169+ checkRelease ( for: key)
170+ }
168171
169- checkRelease ( for: key)
170172 return value
171173 }
172174
@@ -185,7 +187,9 @@ internal struct StoreContext {
185187 func unwatch( _ atom: some Atom , container: SubscriptionContainer . Wrapper ) {
186188 let override = lookupOverride ( of: atom)
187189 let key = AtomKey ( atom, overrideScopeKey: override? . scopeKey)
188- container. subscriptions. removeValue ( forKey: key) ? . unsubscribe ( )
190+
191+ container. subscriptions. removeValue ( forKey: key)
192+ unsubscribe ( [ key] , for: container. key)
189193 }
190194
191195 @usableFromInline
@@ -222,7 +226,7 @@ internal struct StoreContext {
222226
223227 // Release dependencies that are no longer dependent.
224228 if let dependencies = obsoletedDependencies [ key] {
225- checkReleaseDependencies ( dependencies , for : key )
229+ detach ( key , fromDependencies : dependencies )
226230 }
227231
228232 // Notify updates only for the subscriptions of restored atoms.
@@ -232,6 +236,8 @@ internal struct StoreContext {
232236 }
233237 }
234238 }
239+
240+ notifyUpdateToObservers ( )
235241 }
236242}
237243
@@ -266,8 +272,10 @@ private extension StoreContext {
266272 let dependencies = store. graph. dependencies [ key] ?? [ ]
267273 let obsoletedDependencies = oldDependencies. subtracting ( dependencies)
268274
269- // Check if the dependencies that are no longer used and release them if possible.
270- checkReleaseDependencies ( obsoletedDependencies, for: key)
275+ if !obsoletedDependencies. isEmpty {
276+ detach ( key, fromDependencies: obsoletedDependencies)
277+ notifyUpdateToObservers ( )
278+ }
271279 }
272280
273281 // Register the transaction state so it can be terminated from anywhere.
@@ -357,6 +365,17 @@ private extension StoreContext {
357365 }
358366 }
359367
368+ func unsubscribe( _ keys: [ AtomKey ] , for subscriptionKey: SubscriptionKey ) {
369+ let store = getStore ( )
370+
371+ for key in keys {
372+ store. state. subscriptions [ key] ? . removeValue ( forKey: subscriptionKey)
373+ checkRelease ( for: key)
374+ }
375+
376+ notifyUpdateToObservers ( )
377+ }
378+
360379 func invalidate( for key: AtomKey ) -> Set < AtomKey > {
361380 let store = getStore ( )
362381
@@ -377,11 +396,7 @@ private extension StoreContext {
377396 store. state. states. removeValue ( forKey: key)
378397 store. state. subscriptions. removeValue ( forKey: key)
379398
380- // Check if the dependencies are releasable.
381- checkReleaseDependencies ( dependencies, for: key)
382-
383- // Notify release.
384- notifyUpdateToObservers ( )
399+ detach ( key, fromDependencies: dependencies)
385400 }
386401
387402 @discardableResult
@@ -405,10 +420,9 @@ private extension StoreContext {
405420 return true
406421 }
407422
408- func checkReleaseDependencies ( _ dependencies : Set < AtomKey > , for key : AtomKey ) {
423+ func detach ( _ key : AtomKey , fromDependencies dependencies : Set < AtomKey > ) {
409424 let store = getStore ( )
410425
411- // Recursively release dependencies while unlinking the dependent.
412426 for dependency in dependencies {
413427 store. graph. children [ dependency] ? . remove ( key)
414428 checkRelease ( for: dependency)
@@ -481,6 +495,7 @@ private extension StoreContext {
481495
482496 // Release the invalid registration as a fallback.
483497 release ( for: key)
498+ notifyUpdateToObservers ( )
484499 return makeState ( )
485500 }
486501
@@ -510,6 +525,7 @@ private extension StoreContext {
510525
511526 // Release the invalid registration as a fallback.
512527 release ( for: key)
528+ notifyUpdateToObservers ( )
513529 return nil
514530 }
515531
0 commit comments