Sun Jul  3 08:26:55 UTC 2011  pix@kepibu.org
  * Fix some problems discovered on fresh-load
Fri Jul  1 22:52:58 UTC 2011  pix@kepibu.org
  * Expand the timing arguments run-for-a-while takes
Wed Jun 29 03:08:25 UTC 2011  pix@kepibu.org
  * Wrap drakma:http-request so we can have automatic retries on timeouts
Tue Jun 28 17:03:09 UTC 2011  pix@kepibu.org
  * Make #'run-for-a-while take the number of iterations as an argument
Tue Jun 28 08:05:37 UTC 2011  pix@kepibu.org
  * Padding for time numbers, so we get 01 instead of 1
diff -rN -u old-claki/claki.asd new-claki/claki.asd
--- old-claki/claki.asd	2013-06-30 02:24:05.000000000 +0000
+++ new-claki/claki.asd	2013-06-30 02:24:05.000000000 +0000
@@ -1,3 +1,3 @@
 (defsystem :claki
-  :depends-on (:oh-ducks :closure-html :cl-unification :drakma :alexandria :rucksack)
+  :depends-on (:oh-ducks :closure-html :cl-unification :drakma :alexandria :rucksack :local-time)
   :components ((:file "claki")))
diff -rN -u old-claki/claki.lisp new-claki/claki.lisp
--- old-claki/claki.lisp	2013-06-30 02:24:05.000000000 +0000
+++ new-claki/claki.lisp	2013-06-30 02:24:05.000000000 +0000
@@ -6,13 +6,25 @@
 
 #+(or) (clrhash *last-modified*)
 
+(defun http-request (&rest drakma-args)
+  "A wrapper around drakma:http-request which automatically retries the request
+in the event of a timeout."
+  (let ((times-failed 0))
+    (tagbody
+     :fetch-page
+       (handler-case (return-from http-request (apply #'drakma:http-request drakma-args))
+         (usocket:timeout-error ()
+           (sleep (* 60 (expt 2 times-failed)))
+           (incf times-failed)
+           (go :fetch-page))))))
+
 (defun get-cliki-page (url)
   "Returns a page from cliki if it has been modified since we last saw it or nil
 if it has not been modified.  Signals an error otherwise."
   (multiple-value-bind (page status headers)
-      (drakma:http-request (format nil "http://cliki.net/~a" url)
-                           :additional-headers (when (gethash url *last-modified*)
-                                                 `((:if-modified-since (gethash url *last-modified*)))))
+      (http-request (format nil "http://cliki.net/~a" url)
+                    :additional-headers (when (gethash url *last-modified*)
+                                          `((:if-modified-since (gethash url *last-modified*)))))
     ;; FIXME: this doesn't work all that well: it turns out cliki uses a single
     ;; last-modified header for the entire wiki, rather than one per page, so we
     ;; aren't saving ourselves (or cliki) much with this.
@@ -176,14 +188,14 @@
 
 (defun revert-page (url current-version to-version)
   (multiple-value-bind (page status headers)
-      (drakma:http-request (format nil "http://cliki.net/edit/~a" url)
-                           :method :post
-                           :parameters `(("version" . ,current-version)
-                                         ("T0"      . "BODY")
-                                         ("E0"      . ,(get-cliki-source url to-version))
-                                         ("summary" . "Spam detected, reverting to Known-Good.")
-                                         ("captcha" . "lisp")
-                                         ("name"    . "Claki (Revertobot Beta)")))
+      (http-request (format nil "http://cliki.net/edit/~a" url)
+                    :method :post
+                    :parameters `(("version" . ,current-version)
+                                  ("T0"      . "BODY")
+                                  ("E0"      . ,(get-cliki-source url to-version))
+                                  ("summary" . "Spam detected, reverting to Known-Good.")
+                                  ("captcha" . "lisp")
+                                  ("name"    . "Claki (Revertobot Beta)")))
     (declare (ignore headers))
     (cond
       ((and (= status 200)
@@ -198,7 +210,7 @@
 returns the text you should POST to revert a cliki page to the given version."
   (or (find-in-cache url version)
       (multiple-value-bind (page status headers)
-          (drakma:http-request (format nil "http://cliki.net/~a?source&v=~a" url version))
+          (http-request (format nil "http://cliki.net/~a?source&v=~a" url version))
         (declare (ignore headers))
         (cond
           ((= 200 status)
@@ -231,15 +243,16 @@
 (defun seconds (s) s)
 (defun minutes (m) (* (seconds 60) m))
 (defun hours (h) (* (minutes 60) h))
+(defun days (d) (* (hours 24) d))
 (defun plus-or-minus (x y) (+ (- x y) (random (* 2 y))))
 
-(defconstant +simple-time+ '(:year #\- :month #\- :day #\Space :hour #\: :min #\: :sec))
+(defconstant +simple-time+ '(:year #\- (:month 2) #\- (:day 2) #\Space (:hour 2) #\: (:min 2) #\: (:sec 2)))
 (defun now () (local-time:format-timestring nil (local-time:now) :format +simple-time+))
 
-(defun run-for-a-while ()
+(defun run-for-a-while (how-long how-often variance)
   (format t "; Beginning run at ~a~%" (now))
-  (dotimes (i (* 2 24))
-    (sleep (minutes (plus-or-minus 30 5)))
+  (dotimes (i (floor how-long how-often))
+    (sleep (plus-or-minus how-often variance))
     (format t "; Unattended run at ~a~%" (now))
     (unattended-revert-new-spam)
     (save-state))
@@ -247,10 +260,10 @@
 
 #+(or)
  (let ((stdout *standard-output*))
-   (sb-thread:make-thread (lambda () (let ((*standard-output* stdout)) (run-for-a-while)))
+   (sb-thread:make-thread (lambda () (let ((*standard-output* stdout)) (run-for-a-while (days 2) (minutes 30) (minutes 5))))
                           :name "cliki reverter"))
 
-(defvar *state-file* (merge-pathnames #p"state/" (directory-namestring (or #.*load-pathname* #p"/home/pixel/repos/"))))
+(defvar *state-file* (merge-pathnames #p"state/" (directory-namestring (or #.*load-pathname* #p"/home/pixel/repos/claki/"))))
 
 (defmacro with-rucksack-and-transaction ((rucksack) (&rest root-vars) &body body)
   (with-unique-names (rest)