Problem/Motivation

EnabledSourceHandler caches query results in non-volatile storage. But those results never expire. Ever. You have to run a Drush command to clear it out; a regular cache rebuild won't do it, since they're not stored in the regular cache.

This is a problem because it means you can be stuck with outdated results indefinitely, with no way to resolve problem unless you have command-line access.

Proposed resolution

Cache query results with a normal, volatile cache backend, and continue storing actual project information in a permanent key-value collection. Query results should get a cache tag applied so that cached queries can be invalidated in one fell swoop without affecting project data.

We could quick-fix this in EnabledSourceHandler, but the real crux of the problem here (see #6) is architectural -- EnabledSourceHandler has too many responsibilities. Split it into four classes:

  1. Move getCurrentSources() to ProjectBrowserSourceManager::getAllEnabledSources().
  2. Split out onSave to a dedicated event subscriber that knows when to clear storage and invalidate cache tags.
  3. Move getStoredProject and clearStorage into a dedicated ProjectRepository service.
  4. Rename the remainder of EnabledSourceHandler to QueryManager, since it will only be containing querying-related methods (and caching for those queries).
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

phenaproxima created an issue. See original summary.

phenaproxima’s picture

Assigned: Unassigned » phenaproxima
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Been thinking on this a bit more, and the problem comes down to the fact that EnabledSourceHandler stands in deep violation of the single-responsibility principle. It does three things:

  • It's a quasi-plugin manager, only letting us access enabled sources.
  • It's a caching layer for query results.
  • It's a stable, non-volatile repository of every project we have encountered while using Project Browser.

Fully cleaning this up is not in scope here. But I think we can create a cleaner separation between points #2 and #3.

Query results are just that: "when you give me these criteria, here are the projects I found". These should use a normal, volatile cache backend.

Stored projects are relied upon by the activators, so they cannot be subject to volatile caching. Storing projects (and clearing that storage) needs to be -- and is -- a separate operation from querying.

So I think my proposed resolution is correct -- use the cache system for query results, and always update stored projects with whatever the source plugins return. Project object storage, though, should stay as it is, in non-expiring key-value stores.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Assigned: phenaproxima » tim.plunkett
Status: Active » Needs review

Assigning to @tim.plunkett specifically, since this kind of stuff is very much in his wheelhouse.

phenaproxima’s picture

Issue tags: +backport

This should be backported.

phenaproxima’s picture

Decided to expand the scope here to encompass the full clean-up of EnabledSourceHandler into better-scoped, single-responsibility classes. Need to update the issue summary to reflect that.

phenaproxima’s picture

Title: Data cached by EnabledSourceHandler never expires » Refactor EnabledSourceHandler into four separate classes so that query caching is separate from project data storage
Assigned: phenaproxima » tim.plunkett
Issue summary: View changes
Issue tags: -Needs issue rescope, -Needs issue summary update
phenaproxima’s picture

Title: Refactor EnabledSourceHandler into four separate classes so that query caching is separate from project data storage » Refactor EnabledSourceHandler into four separate classes so that query caching is separate from project data storage, and EnabledSourceHandler has only one responsibility
tim.plunkett’s picture

Assigned: tim.plunkett » Unassigned
Status: Needs review » Reviewed & tested by the community

Walked through this with @phenaproxima and asked for one additional code-comment, but this is great work!

chrisfromredfin made their first commit to this issue’s fork.

chrisfromredfin’s picture

Status: Reviewed & tested by the community » Patch (to be ported)

!828 merged to 2.1.x

chrisfromredfin’s picture

Status: Patch (to be ported) » Fixed

and !828 now in 2.0.x

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.