Blocage de notification du Crawler rsky-pds
Problème
Toutes les opérations d'écriture sur rsky-pds (createRecord, putRecord, deleteRecord) se bloquent indéfiniment sans erreur. Le PDS semble sain (l'endpoint health retourne 200, createSession fonctionne) mais aucune opération modifiant le repo ne se termine.
Contexte / Conditions de déclenchement
createSessionretourne un JWT valide instantanémentcreateRecordouputRecordavec ce JWT se bloque indéfiniment (timeout 60s+)- Les logs du PDS affichent uniquement
Rocket has launched from http://0.0.0.0:8000sans erreur - L'endpoint
_healthretourne{"version":"0.3.0-beta.3"}(ou similaire) - Les probes de readiness Kubernetes peuvent échouer par intermittence car le pod est submergé par les requêtes bloquées
- La variable d'env
PDS_CRAWLERSest définie (ex.https://bsky.network)
Solution
Correctif rapide (Runtime)
Désactiver entièrement la variable d'env PDS_CRAWLERS :
# IMPORTANT : Utiliser le tiret final pour DÉSACTIVER, ne pas définir à une chaîne vide
kubectl set env deployment/rsky-pds -n <namespace> PDS_CRAWLERS-
# Attendre le déploiement
kubectl rollout status deployment/rsky-pds -n <namespace> --timeout=120s
NE PAS définir PDS_CRAWLERS="" — le parseur env_list() divise sur les virgules, donc une chaîne vide produit vec![""] (un élément chaîne vide), ce qui cause une "builder error" quand reqwest essaie de construire une URL à partir de "".
Correctif de code (Permanent)
Dans rsky-pds/src/crawlers.rs, ajouter un timeout au client reqwest :
let client = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.timeout(std::time::Duration::from_secs(5)) // Ajouter ceci
.connect_timeout(std::time::Duration::from_secs(3)) // Ajouter ceci
.build()?;
Envisager aussi de rendre l'erreur non-fatale (utiliser let _ = pour ignorer les échecs au lieu de propager avec ?), puisque la notification du crawler n'est pas critique pour le succès de l'opération d'écriture.
Analyse de la cause racine
Le chemin d'écriture dans rsky-pds est :
createRecord->process_writes->format_commit(DB, fonctionne bien)sequence_commit->sequence_evt->crawlers.notify_of_update()(SE BLOQUE)
notify_of_update() dans crawlers.rs crée un reqwest::Client sans timeout configuré et POST à chaque URL de crawler. Depuis un cluster GKE, la requête vers https://bsky.network/xrpc/com.atproto.sync.requestCrawl peut se bloquer au niveau TCP sans réponse, causant l'arrêt de l'ensemble de l'opération d'écriture.
Fichiers clés :
rsky-pds/src/crawlers.rs:30-61— méthodenotify_of_update()rsky-pds/src/sequencer/mod.rs:215— appellecrawlers.notify_of_update()rsky-pds/src/apis/com/atproto/repo/create_record.rs:100— acquiert le verrou du sequencerrsky-common/src/env.rs:28-33— parseurenv_list()qui divise les chaînes vides
Vérification
Après désactivation de PDS_CRAWLERS :
# Devrait retourner en <10 secondes au lieu de se bloquer
curl -X POST "$PDS_URL/xrpc/com.atproto.repo.createRecord" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"repo":"$DID","collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"test","createdAt":"2026-01-01T00:00:00Z"}}'
Notes
- Cela affecte TOUS les déploiements de rsky-pds qui définissent PDS_CRAWLERS à une URL inatteignable
- Le PDS atproto TypeScript en amont a des timeouts appropriés ; c'est un bug spécifique à rsky
notify_of_update()a un throttle de 20 minutes, donc la première écriture après le démarrage déclenche toujours la notification (et se bloque si inatteignable)- Le verrou d'écriture du sequencer à la ligne 99 signifie qu'une seule notification bloquée bloque TOUTES les requêtes d'écriture suivantes, pas seulement celle qui l'a déclenchée