-
Notifications
You must be signed in to change notification settings - Fork 210
Add inline object caching to HPPS repositories #7904
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
base: trunk
Are you sure you want to change the base?
Changes from all commits
ecb33fd
c27bf77
2e32f0a
4e2524c
43c447b
360fc91
3aad620
5fc5d01
9827d82
eedf0ba
bea908b
b3887c7
e8a934d
e656c4c
22a8f33
86fb93a
e3e9440
f48cec8
c892aca
323cf60
c7f4517
30dee5b
d6311ab
d9a3889
c0e8871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| Significance: minor | ||
| Type: added | ||
|
|
||
| Add object caching to HPPS (High-Performance Progress Storage) repositories |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,8 @@ | |||||||||||||||
|
|
||||||||||||||||
| use DateTimeImmutable; | ||||||||||||||||
| use DateTimeZone; | ||||||||||||||||
| use Sensei\Internal\Cache_Prefix; | ||||||||||||||||
| use Sensei\Internal\Services\Progress_Storage_Settings; | ||||||||||||||||
| use Sensei\Internal\Quiz_Submission\Answer\Models\Answer_Interface; | ||||||||||||||||
| use Sensei\Internal\Quiz_Submission\Answer\Models\Tables_Based_Answer; | ||||||||||||||||
| use Sensei\Internal\Quiz_Submission\Submission\Models\Submission_Interface; | ||||||||||||||||
|
|
@@ -26,6 +28,17 @@ | |||||||||||||||
| * @since 4.16.1 | ||||||||||||||||
| */ | ||||||||||||||||
| class Tables_Based_Answer_Repository implements Answer_Repository_Interface { | ||||||||||||||||
| use Cache_Prefix; | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
| * Cache group for quiz answers. | ||||||||||||||||
| * | ||||||||||||||||
| * @since $$next-version$$ | ||||||||||||||||
| * | ||||||||||||||||
| * @var string | ||||||||||||||||
| */ | ||||||||||||||||
| private const CACHE_GROUP = 'sensei_quiz_answers'; | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
| * WordPress database object. | ||||||||||||||||
| * | ||||||||||||||||
|
|
@@ -102,14 +115,20 @@ public function create( Submission_Interface $submission, int $question_id, stri | |||||||||||||||
| ] | ||||||||||||||||
| ); | ||||||||||||||||
|
|
||||||||||||||||
| return new Tables_Based_Answer( | ||||||||||||||||
| $answer = new Tables_Based_Answer( | ||||||||||||||||
| $this->wpdb->insert_id, | ||||||||||||||||
| $submission_id, | ||||||||||||||||
| $question_id, | ||||||||||||||||
| $value, | ||||||||||||||||
| $current_datetime, | ||||||||||||||||
| $current_datetime | ||||||||||||||||
| ); | ||||||||||||||||
|
|
||||||||||||||||
| if ( $this->wpdb->insert_id && Progress_Storage_Settings::is_cache_enabled() ) { | ||||||||||||||||
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return $answer; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| /** | ||||||||||||||||
|
|
@@ -135,6 +154,15 @@ public function get_all( int $submission_id ): array { | |||||||||||||||
| */ | ||||||||||||||||
| $submission_id = (int) apply_filters( 'sensei_quiz_answer_get_all_submission_id', $submission_id, 'tables' ); | ||||||||||||||||
|
|
||||||||||||||||
| $cache_key = $this->get_cache_key( $submission_id ); | ||||||||||||||||
|
|
||||||||||||||||
| if ( Progress_Storage_Settings::is_cache_enabled() ) { | ||||||||||||||||
| $cached = wp_cache_get( self::get_prefixed_key( $cache_key, self::CACHE_GROUP ), self::CACHE_GROUP ); | ||||||||||||||||
| if ( false !== $cached ) { | ||||||||||||||||
| return $cached; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| $query = $this->wpdb->prepare( | ||||||||||||||||
| // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared | ||||||||||||||||
| "SELECT * FROM {$this->get_table_name()} WHERE submission_id = %d", | ||||||||||||||||
|
|
@@ -154,6 +182,10 @@ public function get_all( int $submission_id ): array { | |||||||||||||||
| ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| if ( Progress_Storage_Settings::is_cache_enabled() ) { | ||||||||||||||||
| wp_cache_set( self::get_prefixed_key( $cache_key, self::CACHE_GROUP ), $answers, self::CACHE_GROUP ); | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| return $answers; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -187,6 +219,22 @@ public function delete_all( Submission_Interface $submission ): void { | |||||||||||||||
| '%d', | ||||||||||||||||
| ] | ||||||||||||||||
| ); | ||||||||||||||||
|
|
||||||||||||||||
| if ( Progress_Storage_Settings::is_cache_enabled() ) { | ||||||||||||||||
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); | ||||||||||||||||
|
||||||||||||||||
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); | |
| // Use the same ID transformation as get_all() when computing the cache key. | |
| $cache_submission_id = (int) apply_filters( 'sensei_quiz_answer_get_all_submission_id', $submission->get_id(), 'tables' ); | |
| wp_cache_delete( | |
| self::get_prefixed_key( $this->get_cache_key( $cache_submission_id ), self::CACHE_GROUP ), | |
| self::CACHE_GROUP | |
| ); |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,8 @@ | |||||||
| exit; | ||||||||
| } | ||||||||
|
|
||||||||
| use Sensei\Internal\Cache_Prefix; | ||||||||
| use Sensei\Internal\Services\Progress_Storage_Settings; | ||||||||
| use Sensei\Internal\Quiz_Submission\Answer\Models\Answer_Interface; | ||||||||
| use Sensei\Internal\Quiz_Submission\Grade\Models\Tables_Based_Grade; | ||||||||
| use Sensei\Internal\Quiz_Submission\Grade\Models\Grade_Interface; | ||||||||
|
|
@@ -25,6 +27,17 @@ | |||||||
| * @since 4.16.1 | ||||||||
| */ | ||||||||
| class Tables_Based_Grade_Repository implements Grade_Repository_Interface { | ||||||||
| use Cache_Prefix; | ||||||||
|
|
||||||||
| /** | ||||||||
| * Cache group for quiz grades. | ||||||||
| * | ||||||||
| * @since $$next-version$$ | ||||||||
| * | ||||||||
| * @var string | ||||||||
| */ | ||||||||
| private const CACHE_GROUP = 'sensei_quiz_grades'; | ||||||||
|
|
||||||||
| /** | ||||||||
| * WordPress database object. | ||||||||
| * | ||||||||
|
|
@@ -105,7 +118,7 @@ public function create( Submission_Interface $submission, Answer_Interface $answ | |||||||
| ] | ||||||||
| ); | ||||||||
|
|
||||||||
| return new Tables_Based_Grade( | ||||||||
| $grade = new Tables_Based_Grade( | ||||||||
| $this->wpdb->insert_id, | ||||||||
| $answer_id, | ||||||||
| $question_id, | ||||||||
|
|
@@ -114,6 +127,12 @@ public function create( Submission_Interface $submission, Answer_Interface $answ | |||||||
| $current_date, | ||||||||
| $current_date | ||||||||
| ); | ||||||||
|
|
||||||||
| if ( $this->wpdb->insert_id && Progress_Storage_Settings::is_cache_enabled() ) { | ||||||||
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission->get_id() ), self::CACHE_GROUP ), self::CACHE_GROUP ); | ||||||||
|
||||||||
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission->get_id() ), self::CACHE_GROUP ), self::CACHE_GROUP ); | |
| $submission_id_for_cache = apply_filters( 'sensei_quiz_grade_get_all_submission_id', $submission->get_id() ); | |
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id_for_cache ), self::CACHE_GROUP ), self::CACHE_GROUP ); |
Copilot
AI
Mar 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
save_many() invalidates the cached get_all() result using $submission->get_id(), but get_all() caches under a key derived from the filtered submission ID (sensei_quiz_grade_get_all_submission_id). If the filter changes the ID, the cache entry being read won’t be the one being deleted. Suggest deriving the cache key for invalidation via the same filter/key helper as get_all().
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission->get_id() ), self::CACHE_GROUP ), self::CACHE_GROUP ); | |
| $submission_id = (int) apply_filters( 'sensei_quiz_grade_get_all_submission_id', $submission->get_id(), 'tables' ); | |
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); |
Copilot
AI
Mar 3, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delete_all() deletes the cache entry using the ID filtered by sensei_quiz_grade_delete_all_submission_id, but get_all() reads/writes cache using an ID filtered by sensei_quiz_grade_get_all_submission_id. If those filters return different values, the cached grades list may not be invalidated correctly after deletes. Consider computing invalidation keys using the same ID normalization logic as get_all() (shared helper / apply the same filter) to guarantee consistency.
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); | |
| $cache_submission_id = (int) apply_filters( 'sensei_quiz_grade_get_all_submission_id', $submission->get_id(), 'tables' ); | |
| wp_cache_delete( self::get_prefixed_key( $this->get_cache_key( $cache_submission_id ), self::CACHE_GROUP ), self::CACHE_GROUP ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cache invalidation uses
$submission_idas filtered bysensei_quiz_answer_create_submission_id, butget_all()caches under a key derived fromsensei_quiz_answer_get_all_submission_id. If those filters ever map IDs differently,create()may fail to invalidate theget_all()cache, causing stale reads. Consider deriving the cache key for invalidation using the same ID-normalization logic asget_all()(e.g., apply theget_allfilter or centralize key computation in a helper used by both).