Skip to content
Extraits de code Groupes Projets
Valider 1a9e69d6 rédigé par esj's avatar esj
Parcourir les fichiers

Tentative de stabiliser le code autour de la syndication automatique: [9895]...

Tentative de stabiliser le code autour de la syndication automatique: [9895] avait évacué le verrou spécifique à MySQL, le verrouillage étant assuré par '''cron''', afin d'avoir une méthode portable entre MySQL et PG.. En conséquence IL NE FAUT PAS APPELER '''syndic_a_jour''' sans passer par '''cron'''. Voir source:spip/ecrire/action/editer_site.php pour un exemple.

Les fonctions '''cron''' et '''spip_touch''' distinguent maintenant la valeur False de la valeur 0 afin de forcer un tâche immédiatement au besoin. Ceci devrait corriger le problème signalé dans [10293] sans risquer des accès concurrents. 

La fonction '''syndic_a_jour''' réintègre le répertoire '''genie''' mais est incluse à partir de inc/syndic et signale dans vieilles_def.log quand elle n'est pas appelé par '''cron'''. Cette méthode évite l'erreur grave d'avant [10010] mais signale le danger résiduel.
parent 71c1284c
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -107,8 +107,12 @@ function action_editer_site_dist() {
}
if ($resyndiquer) {
include_spip('inc/syndic');
syndic_a_jour($id_syndic);
// ah si PHP connaisait les fermetures...
// Cette globale est utilisee exclusivement dans la fct suivante.
$GLOBALS['genie_syndic_now'] = $id_syndic;
// forcer l'execution immediate de cette tache
// (i.e. appeler la fct suivante avec gestion du verrou)
cron(0, array('syndic' => -91));
}
// Rediriger le navigateur
$redirect = parametre_url(urldecode(_request('redirect')),
......
......@@ -11,11 +11,218 @@
\***************************************************************************/
if (!defined("_ECRIRE_INC_VERSION")) return;
include_spip('inc/syndic');
function genie_syndic_dist($t) {
define('_GENIE_SYNDIC', 1); // pour message de compatibilite ci-dessous
return executer_une_syndication();
}
//
// Effectuer la syndication d'un unique site,
// retourne 0 si aucun a faire ou echec lors de la tentative
//
// http://doc.spip.org/@executer_une_syndication
function executer_une_syndication() {
spip_connect();
## valeurs modifiables dans mes_options
## attention il est tres mal vu de prendre une periode < 20 minutes
define('_PERIODE_SYNDICATION', 2*60);
define('_PERIODE_SYNDICATION_SUSPENDUE', 24*60);
// On va tenter un site 'sus' ou 'off' de plus de 24h, et le passer en 'off'
// s'il echoue
$where = "syndication IN ('sus','off')
AND statut='publie'
AND date_syndic < DATE_SUB(NOW(), INTERVAL
"._PERIODE_SYNDICATION_SUSPENDUE." MINUTE)";
$row = sql_fetch(sql_select("id_syndic", "spip_syndic", $where, '', "date_syndic", "1"));
if ($row) {
$id_syndic = $row["id_syndic"];
$res1 = syndic_a_jour($id_syndic, 'off');
} else $res1 = true;
// Et un site 'oui' de plus de 2 heures, qui passe en 'sus' s'il echoue
$where = "syndication='oui'
AND statut='publie'
AND date_syndic < DATE_SUB(NOW(), INTERVAL "._PERIODE_SYNDICATION." MINUTE)";
$row = sql_fetch(sql_select("id_syndic", "spip_syndic", $where, '', "date_syndic", "1"));
if ($row) {
$id_syndic = $row["id_syndic"];
$res2 = syndic_a_jour($id_syndic, 'sus');
} else $res2 = true;
return ($res1 OR $res2) ? 0 : $id_syndic;
}
//
// Mettre a jour le site
//
// Attention, cette fonction ne doit pas etre appellee simultanement
// sur un meme site: un verrouillage a du etre pose en amont.
//
// http://doc.spip.org/@syndic_a_jour
function syndic_a_jour($now_id_syndic, $statut = 'off') {
include_spip('inc/texte');
if (!defined('_GENIE_SYNDIC'))
spip_log("syndic_a_jour doit etre appelee par Cron. Cf. " .
"http://trac.rezo.net/trac/spip/changeset/10294",
'vieilles_defs');
$result = spip_query("SELECT * FROM spip_syndic WHERE id_syndic=$now_id_syndic");
if (!$row = sql_fetch($result))
return;
$url_syndic = $row['url_syndic'];
$url_site = $row['url_site'];
if ($row['moderation'] == 'oui')
$moderation = 'dispo'; // a valider
else
$moderation = 'publie'; // en ligne sans validation
spip_query("UPDATE spip_syndic SET syndication='$statut', date_syndic=NOW() WHERE id_syndic=$now_id_syndic");
// Aller chercher les donnees du RSS et les analyser
include_spip('inc/distant');
$rss = recuperer_page($url_syndic, true);
if (!$rss)
$articles = _T('avis_echec_syndication_02');
else
$articles = analyser_backend($rss, $url_syndic);
// Renvoyer l'erreur le cas echeant
if (!is_array($articles)) return $articles;
// Les enregistrer dans la base
$faits = array();
foreach ($articles as $data) {
inserer_article_syndique ($data, $now_id_syndic, $moderation, $url_site, $url_syndic, $row['resume'], $row['documents'], $faits);
}
// moderation automatique des liens qui sont sortis du feed
if (count($faits) > 0) {
$faits = join(",", $faits);
if ($row['miroir'] == 'oui') {
spip_query("UPDATE spip_syndic_articles SET statut='off', maj=maj WHERE id_syndic=$now_id_syndic AND NOT (id_syndic_article IN ($faits))");
}
// suppression apres 2 mois des liens qui sont sortis du feed
if ($row['oubli'] == 'oui') {
sql_delete('spip_syndic_articles', "id_syndic=$now_id_syndic AND maj < DATE_SUB(NOW(), INTERVAL 2 MONTH) AND date < DATE_SUB(NOW(), INTERVAL 2 MONTH) AND NOT (id_syndic_article IN ($faits))");
}
}
// Noter que la syndication est OK
spip_query("UPDATE spip_syndic SET syndication='oui' WHERE id_syndic=$now_id_syndic");
return false; # c'est bon
}
//
// Insere un article syndique (renvoie true si l'article est nouveau)
//
// http://doc.spip.org/@inserer_article_syndique
function inserer_article_syndique ($data, $now_id_syndic, $statut, $url_site, $url_syndic, $resume, $documents, &$faits) {
// Creer le lien s'il est nouveau - cle=(id_syndic,url)
// On coupe a 255 caracteres pour eviter tout doublon
// sur une URL de plus de 255 qui exloserait la base de donnees
$le_lien = substr($data['url'], 0,255);
// Chercher les liens de meme cle
$s = spip_query("SELECT id_syndic_article,titre FROM spip_syndic_articles WHERE url=" . _q($le_lien) . " AND id_syndic=$now_id_syndic ORDER BY maj DESC");
// S'il y a plusieurs liens qui repondent, il faut choisir le plus proche
// (ie meme titre et pas deja fait), le mettre a jour et ignorer les autres
if (spip_num_rows($s) > 1) {
while ($a = sql_fetch($s))
if ($a['titre'] == $data['titre']
AND !in_array($a['id_syndic_article'], $faits)) {
$id_syndic_article = $a['id_syndic_article'];
break;
}
}
// Sinon, s'il y en a un, on verifie qu'on ne vient pas de l'ecrire avec
// un autre item du meme feed qui aurait le meme link
else if ($a = sql_fetch($s)
AND !in_array($a['id_syndic_article'], $faits)) {
$id_syndic_article = $a['id_syndic_article'];
}
// Si l'article n'existe pas, on le cree
if (!isset($id_syndic_article)) {
$ajout = $id_syndic_article = sql_insertq('spip_syndic_articles',
array('id_syndic' => $now_id_syndic,
'url' => $le_lien,
'date' => date("Y-m-d H:i:s", $data['date']),
'statut' => $statut));
if (!$ajout) return;
}
$faits[] = $id_syndic_article;
// Descriptif, en mode resume ou mode 'full text'
// on prend en priorite data['descriptif'] si on est en mode resume,
// et data['content'] si on est en mode "full syndication"
if ($resume != 'non') {
// mode "resume"
$desc = strlen($data['descriptif']) ?
$data['descriptif'] : $data['content'];
$desc = couper(trim(textebrut($desc)), 300);
} else {
// mode "full syndication"
// choisir le contenu pertinent
// & refaire les liens relatifs
$desc = strlen($data['content']) ?
$data['content'] : $data['descriptif'];
$desc = liens_absolus($desc, $url_syndic);
}
// tags & enclosures (preparer spip_syndic_articles.tags)
$tags = $data['enclosures'];
# eviter les doublons (cle = url+titre) et passer d'un tableau a une chaine
if ($data['tags']) {
$vus = array();
foreach ($data['tags'] as $tag) {
$cle = supprimer_tags($tag).extraire_attribut($tag,'href');
$vus[$cle] = $tag;
}
$tags .= ($tags ? ', ' : '') . join(', ', $vus);
}
// Mise a jour du contenu (titre,auteurs,description,date?,source...)
$vals = array(
'titre' => $data['titre'],
'lesauteurs' => $data['lesauteurs'],
'descriptif' => $desc,
'lang'=> substr($data['lang'],0,10),
'source' => substr($data['source'],0,255),
'url_source' => substr($data['url_source'],0,255),
'tags' => $tags);
// Mettre a jour la date si lastbuilddate
if ($data['lastbuilddate'])
$vals['date']= date("Y-m-d H:i:s", $data['lastbuilddate']);
sql_updateq('spip_syndic_articles', $vals, "id_syndic_article=$id_syndic_article");
// Point d'entree post_syndication
pipeline('post_syndication',
array(
$le_lien,
$now_id_syndic,
$data
)
);
return $ajout;
}
?>
......@@ -12,6 +12,12 @@
if (!defined("_ECRIRE_INC_VERSION")) return;
// ATTENTION
// Cette inclusion charge executer_une_syndication pour compatibilite,
// mais cette fonction ne doit plus etre invoquee directement:
// il faut passer par cron() pour avoir un verrou portable
// Voir un exemple dans action/editer/site
include_spip('genie/syndic');
// prend un fichier backend et retourne un tableau des items lus,
// et une chaine en cas d'erreur
......@@ -372,211 +378,4 @@ function cdata_echappe_retour(&$table, &$echappe_cdata) {
$e, $table[$var]);
}
}
//
// Effectuer la syndication d'un unique site,
// retourne 0 si aucun a faire ou echec lors de la tentative
//
// http://doc.spip.org/@executer_une_syndication
function executer_une_syndication() {
spip_connect();
## valeurs modifiables dans mes_options
## attention il est tres mal vu de prendre une periode < 20 minutes
define('_PERIODE_SYNDICATION', 2*60);
define('_PERIODE_SYNDICATION_SUSPENDUE', 24*60);
// On va tenter un site 'sus' ou 'off' de plus de 24h, et le passer en 'off'
// s'il echoue
$where = "syndication IN ('sus','off')
AND statut='publie'
AND date_syndic < DATE_SUB(NOW(), INTERVAL
"._PERIODE_SYNDICATION_SUSPENDUE." MINUTE)";
$row = sql_fetch(sql_select("id_syndic", "spip_syndic", $where, '', "date_syndic", "1"));
if ($row) {
$id_syndic = $row["id_syndic"];
$res1 = syndic_a_jour($id_syndic, 'off');
} else $res1 = true;
// Et un site 'oui' de plus de 2 heures, qui passe en 'sus' s'il echoue
$where = "syndication='oui'
AND statut='publie'
AND date_syndic < DATE_SUB(NOW(), INTERVAL "._PERIODE_SYNDICATION." MINUTE)";
$row = sql_fetch(sql_select("id_syndic", "spip_syndic", $where, '', "date_syndic", "1"));
if ($row) {
$id_syndic = $row["id_syndic"];
$res2 = syndic_a_jour($id_syndic, 'sus');
} else $res2 = true;
return ($res1 OR $res2) ? 0 : $id_syndic;
}
//
// Mettre a jour le site
//
// Attention, cette fonction ne doit pas etre appellee simultanement
// sur un meme site: un verrouillage a du etre pose en amont.
//
// http://doc.spip.org/@syndic_a_jour
function syndic_a_jour($now_id_syndic, $statut = 'off') {
include_spip('inc/texte');
$result = spip_query("SELECT * FROM spip_syndic WHERE id_syndic=$now_id_syndic");
if (!$row = sql_fetch($result))
return;
$url_syndic = $row['url_syndic'];
$url_site = $row['url_site'];
if ($row['moderation'] == 'oui')
$moderation = 'dispo'; // a valider
else
$moderation = 'publie'; // en ligne sans validation
spip_query("UPDATE spip_syndic SET syndication='$statut', date_syndic=NOW() WHERE id_syndic=$now_id_syndic");
// Aller chercher les donnees du RSS et les analyser
include_spip('inc/distant');
$rss = recuperer_page($url_syndic, true);
if (!$rss)
$articles = _T('avis_echec_syndication_02');
else
$articles = analyser_backend($rss, $url_syndic);
// Renvoyer l'erreur le cas echeant
if (!is_array($articles)) return $articles;
// Les enregistrer dans la base
$faits = array();
foreach ($articles as $data) {
inserer_article_syndique ($data, $now_id_syndic, $moderation, $url_site, $url_syndic, $row['resume'], $row['documents'], $faits);
}
// moderation automatique des liens qui sont sortis du feed
if (count($faits) > 0) {
$faits = join(",", $faits);
if ($row['miroir'] == 'oui') {
spip_query("UPDATE spip_syndic_articles SET statut='off', maj=maj WHERE id_syndic=$now_id_syndic AND NOT (id_syndic_article IN ($faits))");
}
// suppression apres 2 mois des liens qui sont sortis du feed
if ($row['oubli'] == 'oui') {
sql_delete('spip_syndic_articles', "id_syndic=$now_id_syndic AND maj < DATE_SUB(NOW(), INTERVAL 2 MONTH) AND date < DATE_SUB(NOW(), INTERVAL 2 MONTH) AND NOT (id_syndic_article IN ($faits))");
}
}
// Noter que la syndication est OK
spip_query("UPDATE spip_syndic SET syndication='oui' WHERE id_syndic=$now_id_syndic");
return false; # c'est bon
}
//
// Insere un article syndique (renvoie true si l'article est nouveau)
//
// http://doc.spip.org/@inserer_article_syndique
function inserer_article_syndique ($data, $now_id_syndic, $statut, $url_site, $url_syndic, $resume, $documents, &$faits) {
// Creer le lien s'il est nouveau - cle=(id_syndic,url)
// On coupe a 255 caracteres pour eviter tout doublon
// sur une URL de plus de 255 qui exloserait la base de donnees
$le_lien = substr($data['url'], 0,255);
// Chercher les liens de meme cle
$s = spip_query("SELECT id_syndic_article,titre FROM spip_syndic_articles WHERE url=" . _q($le_lien) . " AND id_syndic=$now_id_syndic ORDER BY maj DESC");
// S'il y a plusieurs liens qui repondent, il faut choisir le plus proche
// (ie meme titre et pas deja fait), le mettre a jour et ignorer les autres
if (spip_num_rows($s) > 1) {
while ($a = sql_fetch($s))
if ($a['titre'] == $data['titre']
AND !in_array($a['id_syndic_article'], $faits)) {
$id_syndic_article = $a['id_syndic_article'];
break;
}
}
// Sinon, s'il y en a un, on verifie qu'on ne vient pas de l'ecrire avec
// un autre item du meme feed qui aurait le meme link
else if ($a = sql_fetch($s)
AND !in_array($a['id_syndic_article'], $faits)) {
$id_syndic_article = $a['id_syndic_article'];
}
// Si l'article n'existe pas, on le cree
if (!isset($id_syndic_article)) {
$ajout = $id_syndic_article = sql_insertq('spip_syndic_articles',
array('id_syndic' => $now_id_syndic,
'url' => $le_lien,
'date' => date("Y-m-d H:i:s", $data['date']),
'statut' => $statut));
if (!$ajout) return;
}
$faits[] = $id_syndic_article;
// Descriptif, en mode resume ou mode 'full text'
// on prend en priorite data['descriptif'] si on est en mode resume,
// et data['content'] si on est en mode "full syndication"
if ($resume != 'non') {
// mode "resume"
$desc = strlen($data['descriptif']) ?
$data['descriptif'] : $data['content'];
$desc = couper(trim(textebrut($desc)), 300);
} else {
// mode "full syndication"
// choisir le contenu pertinent
// & refaire les liens relatifs
$desc = strlen($data['content']) ?
$data['content'] : $data['descriptif'];
$desc = liens_absolus($desc, $url_syndic);
}
// tags & enclosures (preparer spip_syndic_articles.tags)
$tags = $data['enclosures'];
# eviter les doublons (cle = url+titre) et passer d'un tableau a une chaine
if ($data['tags']) {
$vus = array();
foreach ($data['tags'] as $tag) {
$cle = supprimer_tags($tag).extraire_attribut($tag,'href');
$vus[$cle] = $tag;
}
$tags .= ($tags ? ', ' : '') . join(', ', $vus);
}
// Mise a jour du contenu (titre,auteurs,description,date?,source...)
$vals = array(
'titre' => $data['titre'],
'lesauteurs' => $data['lesauteurs'],
'descriptif' => $desc,
'lang'=> substr($data['lang'],0,10),
'source' => substr($data['source'],0,255),
'url_source' => substr($data['url_source'],0,255),
'tags' => $tags);
// Mettre a jour la date si lastbuilddate
if ($data['lastbuilddate'])
$vals['date']= date("Y-m-d H:i:s", $data['lastbuilddate']);
sql_updateq('spip_syndic_articles', $vals, "id_syndic_article=$id_syndic_article");
// Point d'entree post_syndication
pipeline('post_syndication',
array(
$le_lien,
$now_id_syndic,
$data
)
);
return $ajout;
}
?>
......@@ -613,7 +613,7 @@ function spip_touch($fichier, $duree=0, $touch=true) {
if ((@$f=filemtime($fichier)) AND ($f >= time() - $duree))
return false;
}
if ($touch) {
if ($touch!==false) {
if (!@touch($fichier)) { spip_unlink($fichier); @touch($fichier); };
@chmod($fichier, _SPIP_CHMOD & ~0111);
}
......@@ -632,12 +632,13 @@ function action_cron() {
include_spip('inc/headers');
http_status(204); // No Content
header("Connection: close");
cron (true);
cron (2);
}
// cron() : execution des taches de fond
// quand il est appele par public.php il n'est pas gourmand;
// quand il est appele par ?action=cron, il est gourmand
// Le premier argument indique l'intervalle demande entre deux taches
// par defaut, 60 secondes (quand il est appele par public.php)
// il vaut 2 quand il est appele par ?action=cron, voire 0 en urgence
// On peut lui passer en 2e arg le tableau de taches attendu par inc_genie()
// Retourne Vrai si un tache a pu etre effectuee
......@@ -651,7 +652,7 @@ function cron ($gourmand=false, $taches= array()) {
// ou est trop vieux (> 60 sec), on va voir si un cron est necessaire.
// Au passage si on est gourmand on le dit aux autres
if (spip_touch(_DIR_TMP.'cron.lock-gourmand', 60, $gourmand)
OR $gourmand) {
OR ($gourmand!==false)) {
// Le fichier cron.lock indique la date de la derniere tache
// Il permet d'imposer qu'il n'y ait qu'une tache a la fois
......@@ -659,7 +660,8 @@ function cron ($gourmand=false, $taches= array()) {
// ca soulage le serveur et ca evite
// les conflits sur la base entre taches.
if (spip_touch(_DIR_TMP.'cron.lock', 2)) {
if (spip_touch(_DIR_TMP.'cron.lock',
(is_int($gourmand) ? $gourmand : 2))) {
$genie = charger_fonction('genie', 'inc', true);
if ($genie) {
$genie($taches);
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter