2009-05-27 8 views
1

Ich schreibe ein C# -Programm, das ein spezielles Google Mail-Konto mit POP3 für spezielle Befehls-E-Mails überwacht und entsprechend reagiert.E-Mail-Monitor Synchronisation

Für maximale Zuverlässigkeit werde ich dieses Programm auf mehreren Computern im ganzen Land ausführen. Ich habe derzeit eine Race-Bedingung, wo zwei Instanzen des Programms die gleiche Nachricht lesen können, bevor einer von ihnen löscht, wodurch die Nachricht zweimal verarbeitet wird.

Wie kann ich sicherstellen, dass jeder Befehl genau einmal verarbeitet wird?

Gmails POP3-Zugriff verwendet, um nur jede Nachricht einmal zu liefern (wodurch RETR und DELE eine einzelne atomare Operation), aber ich kann dieses Verhalten nicht mehr reproduzieren.

Die einzige Methode der Kommunikation zwischen den Computern ist ein SQL Server und ein HTTP-Server (die ich kontrolliere).

Antwort

1

Eine Option, an die ich gedacht habe, ist die Verwendung des POP3-Befehls UIDL und eine Tabelle in SQL Server mit einer eindeutigen Spalte von UIDLs, die bereits verarbeitet wurden.

Dann, vor dem Herunterladen jeder Nachricht, würde der Daemon die UIDL in die Tabelle einfügen, und wenn es einen Fehler hat, überspringen Sie die Nachricht. (Ich nehme an, dass der INSERT-Befehl von SQL Server eine atomare Operation ist).

+0

Alles in allem klingt so etwas wie die einzig mögliche Lösung unter den Umständen, mit denen Sie arbeiten müssen. – jerryjvl

+0

beliebiger Beispielcode in C# ?? – Kiquenet

0

Erste ich muss zugeben, ich weiß nicht, was POP3 unterstützt Befehle, aber ... wenn Sie eine explizite ‚DELE‘ tun können, und eine Fehlermeldung erhalten, wenn die Nachricht nicht mehr vorhanden ist, dann würde ich sagen:

  • RETR die Nachricht
  • DELE die Nachricht
  • Prozess nur, wenn DELE

EDIT gelungen:

Nach dem Lesen von RFC1939 sollte dieser Ansatz funktionieren; von der RFC:

DELE msg 

    Arguments: 
     a message-number (required) which may NOT refer to a 
     message marked as deleted 

    Restrictions: 
     may only be given in the TRANSACTION state 

    Discussion: 
     The POP3 server marks the message as deleted. Any future 
     reference to the message-number associated with the message 
     in a POP3 command generates an error. The POP3 server does 
     not actually delete the message until the POP3 session 
     enters the UPDATE state. 

    Possible Responses: 
     +OK message deleted 
     -ERR no such message 

    Examples: 
     C: DELE 1 
     S: +OK message 1 deleted 
      ... 
     C: DELE 2 
     S: -ERR message 2 already deleted 

Dies ist natürlich davon ausgegangen, dass die Gmail-Implementierung tatsächlich die RFC ehrt.

+0

Der DELE-Befehl markiert die Nachricht zum Löschen. Die Nachricht wird erst nach dem Senden von QUIT gelöscht. (Siehe RFC1939) Daher, wenn zwei Daemons die gleiche Nachricht löschen, erhalten sie keine Fehler. – SLaks

+0

Danke für die RFC-Nummer da;) ... schade, dass es nicht hilft. – jerryjvl

+0

Eigentlich ... das Lesen des RFC jetzt, zeigt an, dass die Verwendung einer Nachrichtennummer im DELE, die bereits als gelöscht markiert wurde, ein Fehler ist. Wenn Gmail aufrichtig RFC1939 implementiert, sollte mein Vorschlag funktionieren, in dem Sie eine "ERR" -Antwort anstelle einer "OK" -Antwort für eine Nachricht erhalten, die bereits als gelöscht markiert ist. – jerryjvl