Browse code
refactor: extract entry-point from feed-archiver system
fiddlerwoaroof authored on 14/10/2022 03:11:25
Showing 2 changed files
Showing 2 changed files
... | ... |
@@ -6,38 +6,6 @@ |
6 | 6 |
(defparameter +dirname-format+ |
7 | 7 |
'((:year 4) #\- (:month 2) #\- (:day 2) #\/ (:hour 2) #\- (:min 2) #\/)) |
8 | 8 |
|
9 |
-(defun get-store-directory-name (timestamp) |
|
10 |
- (flet ((make-dirname (timestamp) |
|
11 |
- (merge-pathnames |
|
12 |
- (local-time:format-timestring nil |
|
13 |
- (local-time:timestamp-minimize-part timestamp |
|
14 |
- :sec) |
|
15 |
- :format +dirname-format+) |
|
16 |
- *feed-base*))) |
|
17 |
- (values (prog1-let ((result (make-dirname timestamp))) |
|
18 |
- (ensure-directories-exist result))))) |
|
19 |
- |
|
20 |
-(defun test-feed-list () |
|
21 |
- (values '("http://feeds.feedburner.com/GamasutraFeatureArticles/" |
|
22 |
- "http://edwardfeser.blogspot.com/feeds/posts/default" |
|
23 |
- "http://feeds.feedburner.com/undergroundthomist/yCSy" |
|
24 |
- "https://www.codinghorror.com/blog/index.xml" |
|
25 |
- "https://sancrucensis.wordpress.com/feed/") |
|
26 |
- #p"/tmp/feed-archive/")) |
|
27 |
- |
|
28 |
-(defun init-feeds (&key feed-list archive-root) |
|
29 |
- (ubiquitous:restore 'alimenta.feed-archiver) |
|
30 |
- (let ((default-root (or archive-root |
|
31 |
- (merge-pathnames ".feed-archive/" |
|
32 |
- (truename "~/"))))) |
|
33 |
- (values (ubiquitous:defaulted-value feed-list :feeds) |
|
34 |
- (ubiquitous:defaulted-value default-root :archive :root)))) |
|
35 |
- |
|
36 |
-(defun add-feed (feed) |
|
37 |
- (init-feeds) |
|
38 |
- (pushnew feed |
|
39 |
- (ubiquitous:value :feeds) |
|
40 |
- :test #'equalp)) |
|
41 | 9 |
|
42 | 10 |
(defmacro lambda* ((&rest args) &body body) |
43 | 11 |
(let ((rest-arg (gensym "REST"))) |
... | ... |
@@ -148,68 +116,6 @@ |
148 | 116 |
*feeds*)) |
149 | 117 |
(feed-index index-stream pull-time references))) |
150 | 118 |
|
151 |
-(defun archive-feeds-nondeterm () |
|
152 |
- (let* ((pull-time (local-time:now)) |
|
153 |
- (pull-directory (get-store-directory-name pull-time)) |
|
154 |
- (index-path (merge-pathnames "index.json" pull-directory)) |
|
155 |
- (feed-stream-provider (make-instance 'alimenta.feed-archive.encoders:feed-stream-provider |
|
156 |
- :if-exists :error |
|
157 |
- :root pull-directory))) |
|
158 |
- (with-open-file (index index-path :direction :output) |
|
159 |
- (archive-feeds pull-time |
|
160 |
- feed-stream-provider |
|
161 |
- index)) |
|
162 |
- (format t "~&!! pull-directory ~a~%" (uiop:enough-pathname pull-directory *feed-base*)))) |
|
163 |
- |
|
164 |
-;; This is an ungodly mess, we need to avoid funneling everything through fix-pathname-or-skip |
|
165 |
-(defun command-line-main (&optional (feed-list-initializer #'init-feeds)) |
|
166 |
- (labels ((feed-type-unsupported (c &key (restart 'skip-feed)) |
|
167 |
- (format t "~&Feed type unsupported: ~a for feed ~a~%" |
|
168 |
- (alimenta:feed-type c) |
|
169 |
- (alimenta:feed-link c)) |
|
170 |
- (funcall restart)) |
|
171 |
- (fix-pathname-or-skip (c &key |
|
172 |
- (restart 'skip-feed) |
|
173 |
- (wrapped-condition nil wc-p)) |
|
174 |
- (typecase (or wrapped-condition c) |
|
175 |
- (alimenta:feed-type-unsupported (feed-type-unsupported c)) |
|
176 |
- (t |
|
177 |
- (if (find-restart 'fix-pathname) |
|
178 |
- (fix-pathname) |
|
179 |
- (if (find-restart 'alimenta.pull-feed:skip-feed) |
|
180 |
- (alimenta.pull-feed:skip-feed c) |
|
181 |
- (progn |
|
182 |
- (unless (eq restart 'continue) |
|
183 |
- (format t "~&Skipping a feed... ~s~%" |
|
184 |
- (if wc-p |
|
185 |
- (alimenta.feed-archive.encoders:the-feed c) |
|
186 |
- "Unknown"))) |
|
187 |
- (funcall restart)))))))) |
|
188 |
- |
|
189 |
- (let ((error-count 0)) |
|
190 |
- (handler-bind |
|
191 |
- ((alimenta.feed-archive.encoders:feed-error |
|
192 |
- (op (fix-pathname-or-skip |
|
193 |
- _1 :wrapped-condition |
|
194 |
- (alimenta.feed-archive.encoders:the-condition _1)))) |
|
195 |
- (alimenta:feed-type-unsupported #'feed-type-unsupported) |
|
196 |
- ((or usocket:timeout-error usocket:ns-error cl+ssl:ssl-error-verify) |
|
197 |
- (op (alimenta.pull-feed:skip-feed _))) |
|
198 |
- |
|
199 |
- (error |
|
200 |
- (op |
|
201 |
- (format t "~&Error signaled, ~a (count ~d)" |
|
202 |
- _1 error-count) |
|
203 |
- (incf error-count) |
|
204 |
- (unless (< error-count 15) |
|
205 |
- (format t " continuing~%") |
|
206 |
- (fix-pathname-or-skip _1 :restart 'continue))))) |
|
207 |
- (multiple-value-bind (*feeds* *feed-base*) |
|
208 |
- (funcall feed-list-initializer) |
|
209 |
- (alimenta.pull-feed:with-user-agent ("Feed Archiver v0.1b") |
|
210 |
- (archive-feeds-nondeterm))))))) |
|
211 |
- |
|
212 |
- |
|
213 | 119 |
(defpackage :alimenta.feed-archive/tests |
214 | 120 |
(:use :cl :should-test) |
215 | 121 |
(:export )) |
216 | 122 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,99 @@ |
1 |
+(in-package :alimenta.feed-archive) |
|
2 |
+ |
|
3 |
+(defun directory-for-timestamp (timestamp) |
|
4 |
+ (let* ((rounded (local-time:timestamp-minimize-part timestamp :sec)) |
|
5 |
+ (formatted (local-time:format-timestring nil rounded |
|
6 |
+ :format +dirname-format+))) |
|
7 |
+ (values (parse-namestring formatted)))) |
|
8 |
+ |
|
9 |
+(defun ensure-store-directory (timestamp base) |
|
10 |
+ (prog1-let ((result (merge-pathnames (directory-for-timestamp timestamp) |
|
11 |
+ base))) |
|
12 |
+ (ensure-directories-exist result))) |
|
13 |
+ |
|
14 |
+(defun test-feed-list () |
|
15 |
+ (values '("http://feeds.feedburner.com/GamasutraFeatureArticles/" |
|
16 |
+ "http://feeds.feedburner.com/undergroundthomist/yCSy" |
|
17 |
+ "https://www.codinghorror.com/blog/index.xml") |
|
18 |
+ #p"/tmp/feed-archive/")) |
|
19 |
+ |
|
20 |
+(defun init-feeds (&key feed-list archive-root) |
|
21 |
+ (ubiquitous:restore 'alimenta.feed-archiver) |
|
22 |
+ (let ((default-root (or archive-root |
|
23 |
+ (merge-pathnames ".feed-archive/" |
|
24 |
+ (truename "~/"))))) |
|
25 |
+ (values (ubiquitous:defaulted-value feed-list :feeds) |
|
26 |
+ (ubiquitous:defaulted-value default-root :archive :root)))) |
|
27 |
+ |
|
28 |
+(defun add-feed (feed) |
|
29 |
+ (init-feeds) |
|
30 |
+ (pushnew feed |
|
31 |
+ (ubiquitous:value :feeds) |
|
32 |
+ :test #'equalp)) |
|
33 |
+ |
|
34 |
+(defun archive-feeds-nondeterm () |
|
35 |
+ (let* ((pull-time (local-time:now)) |
|
36 |
+ (pull-directory (ensure-store-directory pull-time *feed-base*)) |
|
37 |
+ (index-path (merge-pathnames "index.json" pull-directory)) |
|
38 |
+ (feed-stream-provider (make-instance 'alimenta.feed-archive.encoders:feed-stream-provider |
|
39 |
+ :if-exists :error |
|
40 |
+ :root pull-directory))) |
|
41 |
+ (with-open-file (index index-path :direction :output) |
|
42 |
+ (archive-feeds pull-time |
|
43 |
+ feed-stream-provider |
|
44 |
+ index)) |
|
45 |
+ (format t "~&!! pull-directory ~a~%" (uiop:enough-pathname pull-directory *feed-base*)))) |
|
46 |
+ |
|
47 |
+;; This is an ungodly mess, we need to avoid funneling everything through fix-pathname-or-skip |
|
48 |
+(defun command-line-main (&optional (feed-list-initializer #'init-feeds)) |
|
49 |
+ (labels ((feed-type-unsupported (c) |
|
50 |
+ (format t "~&Feed type unsupported: ~a for feed ~a~%" |
|
51 |
+ (alimenta:feed-type c) |
|
52 |
+ (alimenta:feed-link c)) |
|
53 |
+ (skip-feed c)) |
|
54 |
+ (fix-pathname-or-skip (c &key (restart 'skip-feed) (wrapped-condition nil wc-p)) |
|
55 |
+ (typecase (or wrapped-condition c) |
|
56 |
+ (alimenta:feed-type-unsupported (feed-type-unsupported c)) |
|
57 |
+ (t |
|
58 |
+ (if (find-restart 'fix-pathname c) |
|
59 |
+ (fix-pathname) |
|
60 |
+ (if (find-restart 'alimenta.pull-feed:skip-feed c) |
|
61 |
+ (alimenta.pull-feed:skip-feed c) |
|
62 |
+ (progn |
|
63 |
+ (unless (eq restart 'continue) |
|
64 |
+ (format t "~&Skipping a feed... ~s~%" |
|
65 |
+ (if wc-p |
|
66 |
+ (alimenta.feed-archive.encoders:the-feed c) |
|
67 |
+ "Unknown"))) |
|
68 |
+ (funcall restart)))))))) |
|
69 |
+ |
|
70 |
+ (let ((error-count 0)) |
|
71 |
+ (handler-bind |
|
72 |
+ ((alimenta.feed-archive.encoders:feed-error |
|
73 |
+ (op |
|
74 |
+ (format t "~&~2t~%Feed Error?~%") |
|
75 |
+ (fix-pathname-or-skip _1 :wrapped-condition |
|
76 |
+ (alimenta.feed-archive.encoders:the-condition _1)))) |
|
77 |
+ (alimenta:feed-type-unsupported #'feed-type-unsupported) |
|
78 |
+ ((or usocket:timeout-error |
|
79 |
+ usocket:ns-error |
|
80 |
+ usocket:socket-error |
|
81 |
+ cl+ssl:ssl-error-verify |
|
82 |
+ storage-condition |
|
83 |
+ type-error) |
|
84 |
+ (op |
|
85 |
+ (format t "~&Error pulling feed, skipping: ~s~%" _1) |
|
86 |
+ (skip-feed _1))) |
|
87 |
+ |
|
88 |
+ (error |
|
89 |
+ (op |
|
90 |
+ (format t "~&Error signaled, ~s (count ~d)" |
|
91 |
+ _1 error-count) |
|
92 |
+ (incf error-count) |
|
93 |
+ (when (< error-count 15) |
|
94 |
+ (format t " continuing~%") |
|
95 |
+ (skip-feed _1))))) |
|
96 |
+ (multiple-value-bind (*feeds* *feed-base*) |
|
97 |
+ (funcall feed-list-initializer) |
|
98 |
+ (alimenta.pull-feed:with-user-agent ("Feed Archiver v0.1b") |
|
99 |
+ (archive-feeds-nondeterm))))))) |