Skip to content

Instantly share code, notes, and snippets.

@chwnam
Last active February 11, 2021 10:01
Show Gist options
  • Save chwnam/c441ca20952856ca0e1a9cd0d657fac9 to your computer and use it in GitHub Desktop.
Save chwnam/c441ca20952856ca0e1a9cd0d657fac9 to your computer and use it in GitHub Desktop.
Race Cond - 옵션 업데이트가 매우 빈번히 일어날 때 주의할 사항
<?php
/**
* Plugin Name: Race Cond
* Plugin URI: https://gist.github.com/chwnam/c441ca20952856ca0e1a9cd0d657fac9
*
* @link https://blog.changwoo.pe.kr/option-race-condition/
*/
add_action( 'admin_menu', 'rcond_admin_menu' );
function rcond_admin_menu() {
add_menu_page( 'RCond', 'RCond', 'administrator', 'rcond', 'rcond_output_menu' );
}
function rcond_output_menu() {
$autoload_yes = get_option( 'rcond_autoload_yes', [] );
$autoload_no = get_option( 'rcond_autoload_no', [] );
?>
<div class="wrap">
<h2>Autoload Yes</h2>
<a href="#" id="autoload-yes-all">모두 동시 클릭</a>
<ul>
<?php for ( $i = 1; $i <= 50; ++ $i ) : ?>
<li>
<a href="#"
class="autoload-yes"
data-id="<?php echo intval( $i ); ?>">
ID #<?php echo intval( $i ); ?> 클릭해 실햄</a>
<?php if ( isset( $autoload_yes[ $i ] ) ) : ?>
<span>clicked</span>
<?php endif; ?>
</li>
<?php endfor; ?>
</ul>
</div>
<div class="wrap">
<h2>Autoload No</h2>
<a href="#" id="autoload-no-all">모두 동시 클릭</a>
<ul>
<?php for ( $i = 1; $i <= 50; ++ $i ) : ?>
<li>
<a href="#"
class="autoload-no"
data-id="<?php echo intval( $i ); ?>">
ID #<?php echo intval( $i ); ?> 클릭해 실햄</a>
<?php if ( isset( $autoload_no[ $i ] ) ) : ?>
<span>clicked</span>
<?php endif; ?>
</li>
<?php endfor; ?>
</ul>
</div>
<hr>
<p>
<button id="reset" type="button" class="button">재설정하기</button>
</p>
<script>
(function ($) {
$('.autoload-yes').on('click', function (e) {
var $this = $(this);
e.preventDefault();
$.ajax('/wp-admin/admin-ajax.php', {
data: {
action: 'rcond_autoload_yes',
id: $this.data('id')
},
success: function () {
$this.after(' <span>clicked</span>');
}
});
});
$('.autoload-no').on('click', function (e) {
var $this = $(this);
e.preventDefault();
$.ajax('/wp-admin/admin-ajax.php', {
data: {
action: 'rcond_autoload_no',
id: $this.data('id')
},
success: function () {
$this.after(' <span>clicked</span>');
}
});
});
$('#reset').on('click', function () {
$.ajax('/wp-admin/admin-ajax.php', {
data: {
action: 'rcond_reset'
},
success() {
window.location.reload();
}
});
});
$('#autoload-yes-all').on('click', function (e) {
e.preventDefault();
$('.autoload-yes').each(function (idx, elem) {
$(elem).trigger('click');
});
});
$('#autoload-no-all').on('click', function (e) {
e.preventDefault();
$('.autoload-no').each(function (idx, elem) {
$(elem).trigger('click');
});
});
})(jQuery);
</script>
<?php
}
add_action( 'wp_ajax_rcond_autoload_yes', 'rcond_autoload_yes' );
function rcond_autoload_yes() {
global $wpdb;
$id = intval( $_GET['id'] ?? '0' );
$value = get_option( 'rcond_autoload_yes', [] );
if ( ! is_array( $value ) ) {
$value = [];
}
$value[ $id ] = true;
update_option( 'rcond_autoload_yes', $value );
wp_send_json_success();
}
add_action( 'wp_ajax_rcond_autoload_no', 'rcond_autoload_no' );
function rcond_autoload_no() {
// DB Locking
// global $wpdb;
//
// $filter_added = false;
// add_filter( 'pre_option_rcond_autoload_no', function ( $value ) use ( &$filter_added ) {
// if ( ! $filter_added ) {
// add_filter( 'query', 'rcond_query_for_update' );
// $filter_added = true;
// }
// return $value;
// } );
//
// wp_suspend_cache_addition( false );
// $wpdb->query( 'SET AUTOCOMMIT = 0;' );
// $wpdb->query( 'START TRANSACTION' );
// Semaphore
// $sem = sem_get( 9090 );
// sem_acquire( $sem );
$id = intval( $_GET['id'] ?? '0' );
$value = get_option( 'rcond_autoload_no', [] );
if ( ! is_array( $value ) ) {
$value = [];
}
$value[ $id ] = true;
update_option( 'rcond_autoload_no', $value, false );
// Semaphore
// sem_release( $sem );
// if ( 50 === count( $value ) ) {
// sem_remove( $sem );
// }
// DB Locking
// $wpdb->query( 'COMMIT' );
wp_send_json_success();
}
function rcond_query_for_update( $query ) {
remove_filter( 'query', 'rcond_query_for_update' );
$query .= ' FOR UPDATE';
return $query;
}
add_action( 'wp_ajax_rcond_reset', 'rcond_reset' );
function rcond_reset() {
update_option( 'rcond_autoload_yes', [], true );
update_option( 'rcond_autoload_no', [], false );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment