Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make PersistenceKeyDefault load its default value lazily #3057

Merged
merged 3 commits into from
May 8, 2024

Conversation

seanmrich
Copy link
Contributor

PersistenceKeyDefault eagerly evaluates its defaultValue. This means every declaration of a Shared value creates a new copy of this value when it's evaluated. Since the normal pattern for persisting shared values is to successfully load from its source, the default value is generated and thrown away without being used.

Additionally, creating this default value can have side effects. Consider a testing context where the default value uses the uuid dependency. Here's a persistence key whose default value creates a Folder value whose initializer generates an id from the current uuid dependency.

extension PersistenceKey where Self == PersistenceKeyDefault<FileStorageKey<Folder>> {
  public static var rootFolder: Self {
    PersistenceKeyDefault(
      .fileStorage(.documentsDirectory.appendingPathComponent("rootFolder", conformingTo: .json)), 
      Folder()
    )
  }
}

Now when running a test that overrides the default with a predetermined value, the creation of the default value has incremented the uuid dependency, even though the value isn't used.

func testAddFolder() async {
  await withDependencies {
    $0.uuid = .incrementing
  } operation: {
    @Shared(.rootFolder) var root = Folder()
    let store = TestStore(
      initialState: Feature.State(),
      reducer: { Feature() }
    )
    await store.send(.addFolderButtonTapped) {
      $0.root.subfolders = [
        Folder(id: UUID(???))
      ]
    }
  }
}

This request modifies PersistenceKeyDefault.defaultValue to lazily evaluate only when the load action fails. It also includes a couple tests to verify the change.

@stephencelis stephencelis merged commit 4c36b18 into pointfreeco:main May 8, 2024
7 checks passed
cgrindel-self-hosted-renovate bot added a commit to cgrindel/rules_swift_package_manager that referenced this pull request May 9, 2024
…ure to from: "1.10.3" (#1063)

This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
|
[pointfreeco/swift-composable-architecture](https://togithub.com/pointfreeco/swift-composable-architecture)
| patch | `from: "1.10.2"` -> `from: "1.10.3"` |

---

### Release Notes

<details>
<summary>pointfreeco/swift-composable-architecture
(pointfreeco/swift-composable-architecture)</summary>

###
[`v1.10.3`](https://togithub.com/pointfreeco/swift-composable-architecture/releases/tag/1.10.3)

[Compare
Source](https://togithub.com/pointfreeco/swift-composable-architecture/compare/1.10.2...1.10.3)

#### What's Changed

- Fixed: Automatically cancel in-flight `TestStore` effects when its
root feature is dismissed
([pointfreeco/swift-composable-architecture#3044).
- Fixed: Propagate current dependencies to `Store.init`
([pointfreeco/swift-composable-architecture#3049).
- Fixed: Runtime warn when stack integration is detected to be missing
from store's reducer
([pointfreeco/swift-composable-architecture#3048).
- Fixed: `TestStore.finish()` should assert against unreceived actions
([pointfreeco/swift-composable-architecture#3054).
- Fixed: Precondition when conflicting persistence keys must match value
by [@&#8203;stephencelis](https://togithub.com/stephencelis) in
[pointfreeco/swift-composable-architecture#3051.

    > **Important:**
> If you have defined a custom persistence key, you may need to
explicitly conform it to `Hashable` after upgrading to this version.
- Fixed: `@Shared` no longer eagerly evaluates its initial value (thanks
[@&#8203;seanmrich](https://togithub.com/seanmrich),
[pointfreeco/swift-composable-architecture#3057).
- Infrastructure: Added a brand new tutorial: Building SyncUps
([pointfreeco/swift-composable-architecture#3039).
- Infrastructure: Add store invalidation test
([pointfreeco/swift-composable-architecture#3038).
- Infrastructure: Document `@CasePathable @&#8203;dynamicMemberLookup`
in 1.4 migration guide
([pointfreeco/swift-composable-architecture#3043).
- Infrastructure: Document nested enum reducers
([pointfreeco/swift-composable-architecture#3050).

#### New Contributors

- [@&#8203;seanmrich](https://togithub.com/seanmrich) made their first
contribution in
[pointfreeco/swift-composable-architecture#3057

**Full Changelog**:
pointfreeco/swift-composable-architecture@1.10.2...1.10.3

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config help](https://togithub.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR has been generated by [Renovate
Bot](https://togithub.com/renovatebot/renovate).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNi4xMDkuNCIsInVwZGF0ZWRJblZlciI6IjM2LjEwOS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiJ9-->

Co-authored-by: Self-hosted Renovate Bot <361546+cgrindel-self-hosted-renovate[bot]@users.noreply.github.enterprise.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants