Skip to content

Commit

Permalink
temp commit
Browse files Browse the repository at this point in the history
  • Loading branch information
hokoo committed May 5, 2024
1 parent f0a58e8 commit 7fab5f8
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 24 deletions.
57 changes: 33 additions & 24 deletions lib/backend/class-wp-lock-backend-db.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,41 +50,50 @@ private function get_lock_key( string $id ): string {
return md5( $id );
}

public function drop_ghosts( $lock_id ) {
global $wpdb;
$ghosts = $this->get_ghosts( $lock_id );

if ( ! empty( $ghosts ) ) {
$wpdb->query( "DELETE FROM {$this->get_table_name()} WHERE id IN (" . implode( ',', $ghosts ) . ")" );
}
}

/**
* Ghost lock is a lock that has no corresponding process and/or connection and has no expiration time.
* Search for a ghost lock for specific lock_id in the database and remove it.
*
* @return void
* @return array List of ghost locks.
*/
public function drop_ghosts( $lock_id ) {
public function get_ghosts( $lock_id ): array {
global $wpdb;

$lock_key = $this->get_lock_key( $lock_id );
$locks = $wpdb->get_results( "SELECT * FROM {$this->get_table_name()} WHERE `lock_key` = '$lock_key'", ARRAY_A );

$locks = $wpdb->get_results( "SELECT * FROM {$this->get_table_name()} WHERE `lock_key` = '$lock_key'", ARRAY_A );
$ghosts = [];
foreach ( $locks as $lock ) {
if ( ! empty( $lock['expire'] ) && $lock['expire'] > microtime( true ) ) {
// This is an unexpired lock, keep it actual. No matter if it's a ghost or not.
continue;
}
// Remove unexpired locks from the list in order to keep them in DB.
$expired = array_filter(
$locks,
fn( $lock ) => empty( $lock['expire'] ) || $lock['expire'] <= microtime( true )
);

if (
( empty( $lock['pid'] ) && empty( $lock['cid'] ) ) ||
( ! empty( $lock['pid'] ) && ! file_exists( "/proc/{$lock['pid']}" ) ) ||
( ! empty( $lock['cid'] ) && empty(
$wpdb->get_var(
$wpdb->prepare( "SELECT id FROM information_schema.processlist WHERE id = %s", $lock['cid'] )
)
) )
) {
// This is a ghost lock, remove it.
$ghosts[] = $lock['id'];
}
if ( empty( $expired ) ) {
return [];
}

if ( ! empty( $ghosts ) ) {
$wpdb->query( "DELETE FROM {$this->get_table_name()} WHERE id IN (" . implode( ',', $ghosts ) . ")" );
}
// Get active CIDs from the database to check whether the given connections are still alive or not.
$active_cids = $wpdb->get_col(
"SELECT id FROM information_schema.processlist WHERE id IN (" .
implode( ',', array_column( $expired, 'cid' ) ) .
")"
);

return array_filter( $expired, function ( $lock ) use ( $active_cids ) {
return
( empty( $lock['pid'] ) && empty( $lock['cid'] ) ) ||
( ! empty( $lock['pid'] ) && ! file_exists( "/proc/{$lock['pid']}" ) ) ||
( ! empty( $lock['cid'] ) && empty( array_filter( $active_cids, fn( $cid ) => $cid == $lock['cid'] ) ) );
} );
}

/**
Expand Down
21 changes: 21 additions & 0 deletions tests/lock/generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,27 @@ public function test_concurrency_pageviews() {
$wpdb->suppress_errors( $suppress_errors );
}

public function test_ghosts( $expiration = 0 ) {
$resource_id = $this->generate_lock_resource_id();

$callback = new WP_Lock_Backend_Callback(
function( $resource_id, $expiration ) {
$lock_backend = new WP_Lock_Backend_DB();
// Born a ghost.
$lock_backend->acquire( $resource_id, WP_Lock::WRITE, false, $expiration );
},
[ $resource_id, $expiration ]
);

run_in_child( array( $callback, 'run' ) );
sleep( 1 + $expiration );
$lock_backend = new WP_Lock_Backend_DB();
$this->assertNotEmpty( $lock_backend->get_ghosts( $resource_id ) );
$this->assertTrue( $lock_backend->acquire( $resource_id, WP_Lock::WRITE, false, 0 ) XOR ! $expiration );
$this->assertEmpty( $lock_backend->get_ghosts( $resource_id ) );
$lock_backend->release( $resource_id );
}

public function _test_concurrency_pageviews_child( $post_id, $resource_id, $lock_backend_class) {
foreach ( range( 1, 100 ) as $_ ) {
$this->_test_concurrency_pageviews_increment_counter( $post_id, $resource_id, $lock_backend_class );
Expand Down

0 comments on commit 7fab5f8

Please sign in to comment.