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

Sunset QLC requirements from cache behaviour #629

Merged

Conversation

Th3-M4jor
Copy link
Contributor

@Th3-M4jor Th3-M4jor commented Aug 18, 2024

See #625 for discussion around why, but the TL;DR is that was decided that while QLC is a cool tech we've had far too many issues with it.

As such we're removing it as a requirement for cache modules to implement, however some cache modules may choose to keep it where it makes sense to do so. Such as the message cache for operations that would require a full table scan anyway.

Caches updated:

  • message cache
  • guild cache
  • channel cache
  • member cache
  • presence cache
  • user cache

@jchristgit
Copy link
Collaborator

Thanks!

Btw, I have a local branch with guild cache and member cache changes, so we don't duplicate any work :-)

jchristgit added a commit that referenced this pull request Aug 18, 2024
See #625 and #629 for further information.
jchristgit added a commit that referenced this pull request Aug 18, 2024
See #625 and #629 for further information.
@jchristgit jchristgit self-assigned this Aug 18, 2024
@jchristgit
Copy link
Collaborator

Btw, I was looking at the message cache QLCs the other day and I think we can replace it with match specs

@jchristgit
Copy link
Collaborator

We are going to win!

@Th3-M4jor
Copy link
Contributor Author

You might be right, match specs or in the case of message eviction using fold when the type isn't an ordered_set.

I'll see what I can come up with for this PR

@Th3-M4jor
Copy link
Contributor Author

Oddly enough, I think we should keep most of them on the Mnesia Message cache for performance reasons.

For example:

iex 1> handle = :nostrum_message_cache_qlc.by_channel_and_author(12345, 5678, 900000, :infinity, Nostrum.Cache.MessageCache.Mnesia)

iex 2> IO.puts(:qlc.info(handle))
ets:match_spec_run(lists:flatmap(fun(V) ->
                                        mnesia:index_read(nostrum_messages,
                                                          V, 3)
                                 end,
                                 [12345]),
                   ets:match_spec_compile([{{'_', '$1', '$2', '$3',
                                             '$4'},
                                            [{'andalso',
                                              {'=<', '$1',
                                               {const, infinity}},
                                              {'andalso',
                                               {'=:=', '$3',
                                                {const, 5678}},
                                               {'andalso',
                                                {'=:=', '$2',
                                                 {const, 12345}},
                                                {'>=', '$1',
                                                 {const, 900000}}}}}],
                                            ['$4']}]))

QLC will be able to leverage indexes, however plain selects don't seem to be able to.

@Th3-M4jor
Copy link
Contributor Author

The only one that seemed to make sense to drop QLC usage on in my opinion was how eviction was done if the type was :set.

The rest would be leveraging indexes, which are generally better performant

@Th3-M4jor Th3-M4jor force-pushed the sunset-global-qlc-cache-functionality branch from 4d1350f to c5a2989 Compare August 18, 2024 20:08
@Th3-M4jor
Copy link
Contributor Author

Maybe long term we consider adding Ecto as an optional dependency and provide our own Ecto Repo backed cache implementations

@Th3-M4jor Th3-M4jor marked this pull request as ready for review August 20, 2024 02:15
@Th3-M4jor
Copy link
Contributor Author

Th3-M4jor commented Aug 20, 2024

This is ready, but I think I'll need to rebase on #630 after its merged before test will actually pass

@jchristgit
Copy link
Collaborator

Maybe long term we consider adding Ecto as an optional dependency and provide our own Ecto Repo backed cache implementations

I thought about this too, I looked at how Adam does it in Coxir and it seems smart, but it's a ton of work and to be honest I'm not a huge fan of locking us into Elixir-only libraries for some reason. If we could do it incrementally I'd be interested but currently I'm not sure how many more cache layer rewrites I have in me 😂

@Th3-M4jor
Copy link
Contributor Author

Let me try to rephrase the above a little.

Similar to how we only compile the Mnesia caches when Mnesia is available, we only compile the Ecto backed ones when the user has Ecto installed and then provide Ecto.SQL migrations that also are only compiled when Ecto.SQL is installed.

No cache rewriting, just another type beyond Mnesia that users can opt-into using instead of the defaults.

I don't think that's locking us into an Elixir-only library as they'd remain optional dependencies?

@jchristgit
Copy link
Collaborator

jchristgit commented Aug 22, 2024 via email

@jchristgit
Copy link
Collaborator

jchristgit commented Aug 22, 2024 via email

@Th3-M4jor Th3-M4jor force-pushed the sunset-global-qlc-cache-functionality branch from d2f746b to 224b88c Compare August 22, 2024 23:11
@Th3-M4jor
Copy link
Contributor Author

There were some minor errors that needed to be fixed after rebasing, so please do review carefully.

we would need to provide our actual library types (e.g.
all structs, or at least those that are cacheable) as Ecto definitions,
wouldn't we?

I was thinking something along the lines of how the mnesia caches operated on fields that we didn't have indexes on. We define a custom Ecto.Type that just calls :erlang.term_to_binary() on the struct before writing in.

Or maybe we dump them as JSON and cast them back when loading, meaning that we just have to make sure all our types impl Jason.Encoder 🤔

@jchristgit
Copy link
Collaborator

jchristgit commented Aug 23, 2024 via email

@jchristgit jchristgit merged commit 8e6e82e into Kraigie:master Aug 23, 2024
10 checks passed
@jchristgit
Copy link
Collaborator

Thanks!

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.

2 participants