@@ -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,12 @@ 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+ // Release the temporarily created state.
169+ // Do not notify update to observers here because refresh doesn't create a new cache.
170+ release ( for: key)
171+ }
168172
169- checkRelease ( for: key)
170173 return value
171174 }
172175
@@ -185,7 +188,9 @@ internal struct StoreContext {
185188 func unwatch( _ atom: some Atom , container: SubscriptionContainer . Wrapper ) {
186189 let override = lookupOverride ( of: atom)
187190 let key = AtomKey ( atom, overrideScopeKey: override? . scopeKey)
188- container. subscriptions. removeValue ( forKey: key) ? . unsubscribe ( )
191+
192+ container. subscriptions. removeValue ( forKey: key)
193+ unsubscribe ( [ key] , for: container. key)
189194 }
190195
191196 @usableFromInline
@@ -222,7 +227,7 @@ internal struct StoreContext {
222227
223228 // Release dependencies that are no longer dependent.
224229 if let dependencies = obsoletedDependencies [ key] {
225- checkReleaseDependencies ( dependencies , for : key )
230+ detach ( key , fromDependencies : dependencies )
226231 }
227232
228233 // Notify updates only for the subscriptions of restored atoms.
@@ -232,6 +237,8 @@ internal struct StoreContext {
232237 }
233238 }
234239 }
240+
241+ notifyUpdateToObservers ( )
235242 }
236243}
237244
@@ -266,8 +273,10 @@ private extension StoreContext {
266273 let dependencies = store. graph. dependencies [ key] ?? [ ]
267274 let obsoletedDependencies = oldDependencies. subtracting ( dependencies)
268275
269- // Check if the dependencies that are no longer used and release them if possible.
270- checkReleaseDependencies ( obsoletedDependencies, for: key)
276+ if !obsoletedDependencies. isEmpty {
277+ detach ( key, fromDependencies: obsoletedDependencies)
278+ notifyUpdateToObservers ( )
279+ }
271280 }
272281
273282 // Register the transaction state so it can be terminated from anywhere.
@@ -357,6 +366,17 @@ private extension StoreContext {
357366 }
358367 }
359368
369+ func unsubscribe( _ keys: [ AtomKey ] , for subscriptionKey: SubscriptionKey ) {
370+ let store = getStore ( )
371+
372+ for key in keys {
373+ store. state. subscriptions [ key] ? . removeValue ( forKey: subscriptionKey)
374+ checkRelease ( for: key)
375+ }
376+
377+ notifyUpdateToObservers ( )
378+ }
379+
360380 func invalidate( for key: AtomKey ) -> Set < AtomKey > {
361381 let store = getStore ( )
362382
@@ -377,11 +397,7 @@ private extension StoreContext {
377397 store. state. states. removeValue ( forKey: key)
378398 store. state. subscriptions. removeValue ( forKey: key)
379399
380- // Check if the dependencies are releasable.
381- checkReleaseDependencies ( dependencies, for: key)
382-
383- // Notify release.
384- notifyUpdateToObservers ( )
400+ detach ( key, fromDependencies: dependencies)
385401 }
386402
387403 @discardableResult
@@ -405,10 +421,9 @@ private extension StoreContext {
405421 return true
406422 }
407423
408- func checkReleaseDependencies ( _ dependencies : Set < AtomKey > , for key : AtomKey ) {
424+ func detach ( _ key : AtomKey , fromDependencies dependencies : Set < AtomKey > ) {
409425 let store = getStore ( )
410426
411- // Recursively release dependencies while unlinking the dependent.
412427 for dependency in dependencies {
413428 store. graph. children [ dependency] ? . remove ( key)
414429 checkRelease ( for: dependency)
@@ -481,6 +496,7 @@ private extension StoreContext {
481496
482497 // Release the invalid registration as a fallback.
483498 release ( for: key)
499+ notifyUpdateToObservers ( )
484500 return makeState ( )
485501 }
486502
@@ -510,6 +526,7 @@ private extension StoreContext {
510526
511527 // Release the invalid registration as a fallback.
512528 release ( for: key)
529+ notifyUpdateToObservers ( )
513530 return nil
514531 }
515532
0 commit comments