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

#145 Define ICache, centralize implementation in Equinox.Core #161

Merged
merged 6 commits into from
Oct 13, 2019

Conversation

DSilence
Copy link
Contributor

I've finally had some free time to hack something together. Here is the summary of changes:

  1. Added to interfaces ICache interface (note that it's async based). Moved the CacheEntry type nearby, changed the Token.supersedes logic to be customizable. Added new CacheEntryOptions which is a more abstract way to configure the behavior of cache items (relative/absolute expiration).
  2. Removed store-specific cache logic.
  3. Extracted System.Runtime.Caching integration into a separate project. The implementation remains the same.
  4. Added Microsoft.Extensions.Caching implementation. Couldn't find a good way to customize the way it calculates object size (which wasn't terribly slow) so added a way to customize it via constructor parameter.
    The distributed cache implementation is also pretty straightforward given that there is an abstraction here now.
    Looking forward to feedback!

@CLAassistant
Copy link

CLAassistant commented Sep 21, 2019

CLA assistant check
All committers have signed the CLA.

@bartelink
Copy link
Collaborator

Thanks for doing this work; from first glance it looks pretty complete.

Quick thoughts:

  • It comes at a good point as Support SqlStreamStore #62 is in progress and is about to add another store that can definitely benefit from a cache. @Rajivhost
  • I'm thinking I'd like to consider overlaps with Add ResolveOption.AllowStale to Resolver #157 and Cosmos: Provide ability to separate storage of snapshots #61 before releasing (might take a run at Add ResolveOption.AllowStale to Resolver #157 in a bit and we can see if the outcome of that helps in any way)
  • I'd definitely like a prefix on the names of the Cache impl packages - i.e. Equinox.Cache.SystemRuntime and Equinox.Caching.MicrosoftExtensions or similar naming style in alignment with how FsCodec name plugins
  • 🤔 I guess we have integration tests but I'm wondering about whether there's a good way to do unit tests
  • 🤔 maybe the cache interface should go somewhere other than in the core Equinox assembly (there are some StoreHelpers that are inlined into each store impl which maybe should go into an Equinox.Storage package) - the fact that Equinox.dll has 240 lines of fs including comments is important (at least to me) - not saying it needs to happen as part of this; ultimately this makes the codebase more intelligible and we can likely best refactor from there onwards
  • 🤔 I'm still slightly concerned about what something other than SRC actually buys anyone as noted in Customizing cache implementation #145

Probably won't get to take a deeper look today but hopefully shortly

@bartelink
Copy link
Collaborator

Some follow-on points:

  • having a clear interface (especially if some unit tests and/or docs can use it)
  • extracting the impls from the store impl files is a win
  • it's not a major problem to introduce a new package in the main repo from a CI/CD point of view

despite suggesting introducing new packages, I'm keen to

  • reduce the number of packages that need to be documented and/or considered by someone doing a 101 sample
  • default to embedding/hiding stuff that's not something that most folks need to worry about
  • not have single user features - i.e. a Microsoft.Extensions.Caching impl would need to be something everyone needs to justify putting it in the repo (right now I can't see a reason for anyone other than you to use it; until we have proof to the contrary I'm thinking that's a good way to look at it)
  • while I know it's correct from many perspectives, a tree of packages or folders as big as https://github.com/eventflow/EventFlow/tree/develop/Source is a nightmare for me - being able to simply clone EventStore.fs in an application to hack around a bug or add a some logging is for me an important feature of having essentially 3 files of consequence in Equinox as a whole if you get my drift

This is making me think the best approach should be along the following lines

  1. extract the interface and provide the seam - probably initially into the Equinox DLL
  2. you can validate by having your caching impl in a separate assembly, satisfying yourself it works
  3. initially we leave the SRC impl in each store for now
  4. at such time as a stronger need for an Equinox.Storage DLL presents itself, move ICache and the default impl there
  5. iff there's a reason to have more that one new DLL, consider having the SRC cache impl in its own assembly
  6. if there was a Equinox.Cache.SRC and >2 users of Equinox.Cache.MEC, then hosting it in the main repo would start to make sense

For now, I'd be comfortable with working step 1, but prior to taking most of the other steps, I'd be looking to:

Does any of this seem reasonable to you?

@bartelink
Copy link
Collaborator

bartelink commented Sep 29, 2019

I'm looking to implement #157 and #61 soon - ideally that'd be after this gets rebased and/or cherrypicked onto master now #164 is complete.
@DSilence do you see any time opening up to do that your side any time soon? Centralizing the SRC impl would make a great addition for a V2 release (esp if/when SqlStreamStreamStore support arrives #62), and hopefully shouldn't be too much work given you've done the hard bit ;)

@bartelink bartelink added this to the 2.0 milestone Sep 29, 2019
@DSilence
Copy link
Contributor Author

Agree with the points above.
While I would personally prefer extra modularity in assemblies, given that you want to keep things simple for now I'm totally fine to go with your suggestions.

I've updated the PR and rebased it on the latest master. The interface (and related base types) were moved to Core package (to a separate Cache.fs file), and implementations are made part of EventStore.fs and Cosmos.fs. My only issue with that is that those packages remain dependent on System.Runtime.Caching - even if another caching library is used, but it's something I can live with 😄.
The Microsoft.Extensions.Caching integration package was removed for now - I might end up publishing it as a separate package (or make a blog post with the implementation sample) if you don't mind.

@bartelink
Copy link
Collaborator

Thanks! Given it wouldn't materially affect ones dependency tree, what would you think about moving to a single impl of Cache as Equinox.Cache but housed in the Equinox.Core package (one thing prompting this is that we're about to sprout SqlStreamStore support, another is that i can simplify the wiring in eqxweb) ?
Blog posts, articles, edits to DOCUMENTATION.md are all more than welcome any time of course ;)

@DSilence
Copy link
Contributor Author

All up for it. I'll update the pull request.

@DSilence
Copy link
Contributor Author

Done, please take a look.

@bartelink
Copy link
Collaborator

Looks great. Some minor picky comments regarding my/house style adherence added.

@bartelink bartelink changed the title #145 Added: initial cache implementation. #145 Define ICache, centralize implementation in Equinox.Core Oct 13, 2019
@bartelink
Copy link
Collaborator

🎉Looks perfect now; thanks for bearing with me over the course of all the iterations.
Aside from opening up the extension point, the forcing of the introduction of Equinox.Core and moving the cache impls to a central location really improves the legibility and hence approachability of the store implementation files. Merging now cc
@Rajivhost

@bartelink bartelink merged commit 9136c0a into jet:master Oct 13, 2019
@DSilence DSilence deleted the feature/caching branch October 13, 2019 13:02
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.

3 participants