#2879 - Remove Associated Storage S3 Objects During Record Deletion#2896
Conversation
kodinkat
commented
Feb 24, 2026
- fixes: Remove Associated Storage S3 Objects During Record Deletion #2879
…deletion
- Implemented a new private method to remove S3-backed storage objects associated with a post, including image fields in post meta, comment attachments, and user meta.
- Integrated this method into the delete_post function to ensure storage cleanup occurs during post deletion.
- Added checks for the availability of DT_Storage_API to prevent errors if the API is not enabled.
Code ReviewOverall the approach is well-structured and the placement of A few issues worth addressing: 1. Silent failure on S3 delete errors (medium)
// current
DT_Storage_API::delete_file( $storage_key );
// suggested: at minimum log failures so they can be investigated
$result = DT_Storage_API::delete_file( $storage_key );
if ( $result === null ) {
dt_write_log( "purge_post_storage_objects: failed to delete S3 object '{$storage_key}' for post {$post_id}" );
}This is a best-effort cleanup (acceptable), but without logging there is no way to audit or recover orphaned objects. 2. Empty-value check inconsistency (minor)The post-meta section uses // inconsistent
if ( !empty( $storage_key ) ) { ... } // post meta
if ( empty( $meta_key ) || $meta_value === '' ) { continue; } // post_user_meta
// consistent
if ( empty( $meta_key ) || empty( $meta_value ) ) { continue; }3. No test coverageThe new method has no corresponding tests. The existing test suite already covers 4. Performance note (low priority / informational)Each file is deleted via a separate What looks good
|
- Updated the purge_post_storage_objects method to log failures when deleting S3 objects associated with posts, ensuring better tracking of issues during storage cleanup.
- Added checks for the result of DT_Storage_API::delete_file to log a message if the deletion fails, improving the robustness of the storage management process.
Code ReviewThanks for addressing issue #2879. The overall approach is correct—reading S3 keys from the DB before deleting the DB records ensures the data needed for cleanup is available. Here are some issues worth addressing: Bug: Incomplete failure detection in
|
|
@corsacca review ready.... |
Code ReviewThanks for this PR! Cleaning up S3 objects on post deletion is important for avoiding orphaned storage. Overall the approach is solid, but there are a few issues to address. Bug: Empty filter array causes invalid SQLIn $comment_storage_meta_keys = apply_filters( 'dt_post_comment_storage_meta_keys', [ 'audio_url', 'image_url' ] );
$placeholders = implode( ', ', array_fill( 0, count( $comment_storage_meta_keys ), '%s' ) );
// If empty: AND cm.meta_key IN ( ) <- invalid SQL, causes DB errorAdd a guard before the query: $comment_storage_meta_keys = apply_filters( 'dt_post_comment_storage_meta_keys', [ 'audio_url', 'image_url' ] );
if ( !empty( $comment_storage_meta_keys ) ) {
// run the comment meta query
}Issue: S3 deletion happens before DB deletion (ordering risk)
Consider calling // After all DB deletes, before/within dt_post_deleted hook
self::purge_post_storage_objects( $post_type, $post_id );
do_action( 'dt_post_deleted', $post_type, $post_id, $post_title );Performance: Filter called inside a loop in dt-posts.phpIn foreach ( $comments_meta as $meta ) {
// ...
$comment_storage_meta_keys = apply_filters( 'dt_post_comment_storage_meta_keys', [ 'audio_url', 'image_url' ] ); // called every iteration
if ( in_array( $meta->meta_key, $comment_storage_meta_keys ) && ... ) {This runs $comment_storage_meta_keys = apply_filters( 'dt_post_comment_storage_meta_keys', [ 'audio_url', 'image_url' ] );
foreach ( $comments_meta as $meta ) {
// ...
if ( in_array( $meta->meta_key, $comment_storage_meta_keys ) && ... ) {Minor: Incomplete failure logging for
|
Code ReviewThe approach is sound: purging S3 objects before the DB rows are deleted ensures the storage keys are still retrievable when needed. The three-phase cleanup (post meta → comment meta → dt_post_user_meta) is thorough, and the defensive guard ( A few issues are worth addressing before merge: 1.
|
- Enhanced the error handling for S3 object deletions in both the and comment processing methods, ensuring that failures are logged correctly.
- Introduced a filter for comment storage meta keys to streamline the deletion process for associated audio and image URLs.
- Improved code readability and maintainability by consolidating repeated logic for checking and deleting S3 objects.
Code ReviewThis PR correctly addresses #2879 by cleaning up S3 storage objects before the database records are deleted (so keys are still readable). The overall structure is solid and the changes in What is good
Issues worth addressing1. N+1 queries in the post-meta image loop (performance)
$all_post_meta = get_post_meta( $post_id ); // one query upfront
foreach ( $field_settings as $field_key => $settings ) {
if ( isset( $settings['type'] ) && $settings['type'] === 'image' ) {
$storage_key = $all_post_meta[ $field_key ][0] ?? '';
if ( !empty( $storage_key ) ) {
// ... delete logic
}
}
}The format from 2. dt_post_user_meta query fetches all rows, then does O(n x m) field lookupThe query retrieves every user-meta row for the post regardless of field type, then calls A lighter approach: collect image-type field keys first, then add a 3. No unit tests for purge_post_storage_objectsThis method has no test coverage. Given that it is a destructive, side-effectful operation called during 4. Filter applied in three independent locations
private static function get_comment_storage_meta_keys(): array {
return apply_filters( 'dt_post_comment_storage_meta_keys', [ 'audio_url', 'image_url' ] );
}SummaryThe core logic is correct and this is a meaningful improvement. Main things to consider before merging:
The |
…etion logic
- Introduced a new method, get_comment_storage_meta_keys, to centralize the retrieval of comment meta keys backed by storage, enhancing code maintainability.
- Updated the purge_post_storage_objects method to utilize the new retrieval method, streamlining the process of deleting S3 objects associated with comments.
- Improved SQL query preparation for fetching comment storage keys, ensuring better performance and security.
Code Review — PR #2879: Remove Associated Storage S3 Objects During Record DeletionGood addition overall. Cleaning up S3 objects before DB records are deleted is the right approach, and the extensibility points (filter + action) are solid design. Here are my observations: Issues1. Hook ordering risk (medium)
The docstring says "The purge runs before database deletes so that storage keys can be read" — this is true for the DB deletes, but not for the
2. In $field_settings = DT_Posts::get_post_field_settings( $post_type );Since 3. Visibility inconsistency (minor)
4. This fetches all user-meta rows for the post and then filters by image-type field in PHP. At delete time this is acceptable, but it could be more efficient by pre-computing the set of image field keys and adding 5.
Positive notes
SummaryThe core logic is sound. The main thing worth addressing before merge is issue #1 (hook ordering) — the rest are style/minor improvements. No security concerns identified. |
…ools-theme into 2879-remove-associated-storage-s3-objects-during-record-deletion
- Improved the SQL query construction for fetching comment storage keys by consolidating the query into a single prepared statement, enhancing performance and security.
- Added a PHPCS ignore comment to clarify the safety of the constructed placeholders.
Code ReviewThis PR correctly addresses #2879. The three-phase purge (post meta → comment meta → A few remaining items worth addressing before merge: 1. Visibility inconsistency — minor
2. Hook-ordering constraint not documented — minorThe docblock says "The purge runs before database deletes", which is accurate. However, the call is placed after * Note: this runs after the dt_before_post_deleted action. Plugins hooked into
* dt_before_post_deleted must not delete or modify storage-key meta if they
* want S3 cleanup to complete correctly.3. Parent calling child class — minor, consistent with existing codebaseInside $field_settings = DT_Posts::get_post_field_settings( $post_type );
4. No unit tests — minorThe new deletion path has no test coverage. Given that What looks good
|
…y retrieval
- Disabled PHPCS warning for interpolated SQL queries to clarify the safety of constructed placeholders.
- Re-enabled the warning after the SQL query preparation to maintain code quality standards.
PR Review: Remove Associated Storage S3 Objects During Record DeletionOverall this is a well-structured implementation that addresses a real data hygiene gap. The approach is sound and follows existing codebase patterns. Below are my findings. Positive aspects
Issues / Suggestions1.
|
|
@corsacca review ready.... |
|
Thanks @kodinkat! |