2010-04-20 6 views
0

Je travaille sur un plugin personnalisé de dripper de contenu dans WordPress que mon client m'a demandé de construire. Il dit qu'il veut qu'il attrape un événement de vue de page, et si c'est le bon moment de la journée (24 heures depuis le dernier post), tirer d'un fichier de ressources et sortir un autre post. Il en avait besoin pour élever un drapeau et empêcher les autres sessions de tirer le même bout de code. Ainsi, soulevez une sorte de drapeau en disant: «Je poste ce message, éloignez-moi d'un autre processus», puis il publie ce message et relâche le drapeau. Cependant, la chose la plus étrange se produit lorsqu'il est placé sous charge avec plusieurs sessions frappant le site avec des pages vues. Il tire au lieu d'un message - il fait au hasard 1, 2 ou 3 messages supplémentaires, chacun pensant que c'était le bon moment pour poster, car il était 24 heures après le dernier message. Parce que c'est quelque peu aléatoire, je suppose que le problème est une sorte de mise en cache d'écriture où les autres sessions ne voient pas le drapeau levé jusqu'à ce que quelques microsecondes passent.WordPress Write Cache Problème avec plusieurs sessions

Le plugin levait le "drapeau" en écrivant simplement dans la table wp_options avec l'API update_option() dans WordPress. Les autres sessions utilisateur étaient censées lire cette valeur avec get_option() et voir l'indicateur, puis ne pas exécuter le morceau de code qui crée le message car une session donnée le faisait déjà. Puis, quand c'est fait, je baisse le drapeau et les autres sessions continuent comme d'habitude.

Mais ce qu'il fait est de laisser les autres séances.

Pour faire ce travail, j'utilisais add_action (« loop_start », « checkToAddContent »). La chose étrange à propos de cette fonction est qu'elle est appelée plus d'une fois sur une page, et en fait certains plugins peuvent l'appeler. Je ne sais pas s'il y a un meilleur événement à accrocher. Même encore, même si je trouve un événement à accrocher qui ne fonctionne qu'une seule fois sur une page, j'ai encore plusieurs sessions à gérer (différents utilisateurs qui peuvent voir la page en même temps) et je veux qu'une seule session donnée se déclenche le contenu du message lorsque le message est dû sur le calendrier. Je me demande s'il existe des développeurs de plugins WordPress qui pourraient suggérer un autre hook d'événement à verrouiller, et trouver un autre moyen de lever un drapeau que toutes les sessions verront. Je veux dire, je pourrais utiliser l'API de mémoire partagée en PHP, mais de nombreux plans d'hébergement ont désactivé. Impossible d'utiliser un cookie ou une session var car il s'agit d'une seule session. À propos de la seule chose qui pourrait fonctionner à travers les plans d'hébergement serait de laisser tomber un fichier comme un drapeau, à la place. Si le fichier est présent, alors une session a le drapeau. Si le fichier n'est pas présent, les autres sessions peuvent tenter d'obtenir le drapeau. Bien sûr, je pourrais utiliser la route des fichiers, mais c'est un peu immature à mon avis et je me demandais s'il y avait quelque chose dans WordPress que je pouvais faire.

+0

La version Twitter comme ceci: Qu'est-ce qu'un moyen de lever un drapeau dans wordpress que toutes les sessions voient? L'update_option() a une latence. D'autres sessions ne le voient pas à temps. – Volomike

+0

Je suis passé un peu plus loin. Quelqu'un a suggéré d'éviter 'loop_start' et d'utiliser l'événement 'wp'. Ensuite, dans cet événement, exécutez le code à l'intérieur de if (is_single() || is_page() || is_home() || is_archive() || is_category() || is_tag()) {// ajoute du code ici}. Ne résout toujours pas le problème du drapeau, mais c'est un meilleur événement à utiliser car il ne s'exécute qu'une seule fois par page. – Volomike

Répondre

0

Le problème se pose de la sorte avec les demandes de page même à partir de la même session (même visiteur), mais peut également se produire avec des demandes de pages provenant de visiteurs distincts. Il fonctionne comme ceci:

  • Si vous faites ruisselant de contenu, puis une demande de page est probablement ce que vous intercepter avec add_action (« wp », « myPageRequest »). À partir de là, si un message planifié est dû, vous créez le nouveau message.

  • La publication prend un peu de temps pour écrire dans la base de données. Dans ce cas, une requête sur get_posts() peut ne pas voir ce nouvel enregistrement pour le moment. Il peut réellement déclencher votre morceau de code pour créer un nouveau poste quand on a déjà été placé.

Le correctif est de forcer WordPress pour vider le cache d'écriture semble être ceci:

try { 
    $asPosts = array(); 
    $asPosts = @ wp_get_recent_posts(1); 
    foreach($asPosts as $asPost) {break;} 
    @ delete_post_meta($asPost['ID'], '_thwart'); 
    @ add_post_meta($asPost['ID'], '_thwart', '' . date('Y-m-d H:i:s')); 
} catch (Exception $e) {} 
$asPosts = array(); 
$asPosts = @ wp_get_recent_posts(1); 
foreach($asPosts as $asPost) {break;} 
$sLastPostDate = ''; 
@ $sLastPostDate = $asPost['post_date']; 
$sLastPostDate = substr($sLastPostDate, 0, strpos($sLastPostDate, ' ')); 
$sNow = date('Y-m-d H:i:s'); 
$sNow = substr($sNow, 0, strpos($sNow, ' ')); 
if ($sLastPostDate != $sNow) { 
    // No post today, so go ahead and post your new blog post. 
    // Place that code here. 
} 

La première chose que nous faisons est d'obtenir le poste le plus récent. Mais nous ne nous soucions pas vraiment si ce n'est pas le post le plus récent ou pas. Tout ce que nous recevons pour est d'obtenir un ID Post, puis nous ajoutons un champ personnalisé caché (donc le trait de soulignement il commence par) appelé

_thwart

... comme dans , contrecarrer le cache d'écriture en publiant quelques données à la base de données qui n'est pas trop lourd CPU. Une fois cela en place, nous utilisons à nouveau wp_get_recent_posts (1) pour voir si le post le plus récent n'est pas la date d'aujourd'hui. Si ce n'est pas le cas, alors il est clair qu'il y a un peu de contenu. (Ou, si vous voulez seulement égoutter comme toutes les 72 heures, etc., vous pouvez changer cela un peu ici.)

1

La clé peut être de créer un enregistrement de sémaphore dans la base de données pour l'événement "goutte à goutte".

Avertissement - considérez le pseudo-code suivant - je ne recherche pas les fonctions.

Lorsque le poste est interrogé, utilisez une instruction SQL comme

$ts = get_time_now(); // or whatever the function is 
$sid = session_id(); 

INSERT INTO table (postcategory, timestamp, sessionid) 
VALUES ("$category", $ts, "$sid") 
WHERE NOT EXISTS (SELECT 1 FROM table WHERE postcategory = "$category" 
    AND timestamp < $ts - 24 hours) 

l'intégrité de la base de données fera cette atomique si un seul enregistrement peut être inséré. et l'insertion n'aura lieu que si le laps de temps a été dépassé. Ensuite, vérifiez immédiatement si l'identifiant session_id() actuel et l'horodatage sont les vôtres. Si c'est le cas, dégouttez.

SELECT sessionid FROM table OU postcategory = "postcategory de $" ET timestamp = $ ts ET sessionid = "$ sid"