Skip to content

Cache improvements#3117

Draft
brianhogg wants to merge 9 commits intodevfrom
cache-improvements
Draft

Cache improvements#3117
brianhogg wants to merge 9 commits intodevfrom
cache-improvements

Conversation

@brianhogg
Copy link
Copy Markdown
Contributor

Description

Handling of empty string cached values when determining if a cached value should be re-calculated, for grades

Fixes #3116

How has this been tested?

Manually

Checklist:

  • This PR requires and contains at least one changelog file.
  • My code has been tested.
  • My code passes all existing automated tests.
  • My code follows the LifterLMS Coding & Documentation Standards.

Persistent object caches (Redis, Memcached) can deserialize null
values as empty string during serialization round-trip. Since
calculate_grade() legitimately returns null for posts with no
gradable content, this null gets cached and later retrieved as ''.

The existing check `false === $grade` does not match '', so the
empty string is treated as a valid cached grade. It then bypasses
the is_null() conversion to "N/A" in LLMS_Student::get_grade()
and propagates to rendering code as 0%.

Normalizes '' to false in get_grade_from_cache() so the standard
cache-miss logic triggers recalculation.

Made-with: Cursor
When a quiz attempt ends, only the usermeta overall_grade was cleared.
The wp_cache entries for the quiz, lesson, and course grades were left
intact. On sites with persistent object caches (Redis, Memcached),
these stale entries persisted across requests, preventing recalculation
of grades after quiz completion.

Adds wp_cache_delete calls for the quiz, lesson, and parent course
grade cache keys in the student's cache group.

Made-with: Cursor
Persistent object caches (Redis, Memcached) can deserialize null
as empty string. Both get_enrollment_date() and get_enrollment_status()
cache null values from $wpdb->get_var() and check for false === to
detect cache misses.

While these methods happen to produce correct results due to
downstream truthiness checks, the stale empty string prevents cache
self-healing. Adding '' === checks ensures a fresh DB query runs
when a corrupted null is encountered.

Made-with: Cursor
Tests that get_grade() correctly handles cache values that may
be corrupted by Redis/Memcached serialization round-trips:

- Empty string in cache (deserialized null) triggers recalculation
- Numeric grade in cache is returned as-is
- Null in cache is treated as a valid "no grade" hit

Made-with: Cursor
@ideadude ideadude moved this to Awaiting Review in Development Apr 2, 2026
@brianhogg brianhogg moved this from Awaiting Review to Review in Progress in Development Apr 2, 2026
@brianhogg brianhogg added this to the 10.0 milestone Apr 2, 2026
@brianhogg
Copy link
Copy Markdown
Contributor Author

Need to test and verify this doesn't create a marked increase in attempts to re-try the grade calculation early.

@brianhogg brianhogg marked this pull request as draft April 7, 2026 14:00
@ideadude ideadude self-requested a review April 8, 2026 16:47
@ideadude ideadude moved this from Review in Progress to Awaiting Review in Development Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Awaiting Review

Development

Successfully merging this pull request may close these issues.

2 participants