diff options
author | Christopher R. Nelson <christopher.nelson@languidnights.com> | 2024-01-17 21:05:37 -0500 |
---|---|---|
committer | Christopher R. Nelson <christopher.nelson@languidnights.com> | 2024-01-21 09:59:03 -0500 |
commit | a6721bdd6154e2bebd8ab07bf310c25629347a21 (patch) | |
tree | 2b0dad144829f726396b08f09a5eaba3c9b18615 | |
parent | 2f84ed3f877d97d2327f526ccbe981a6fe3acade (diff) |
Add shutdown command, and refactor server impl
zmq: refactor server to functions
add shutdown function (end recursion)
media: fix bug with missing directories
rh-client: support shutdown function
rh-server: update to use build variables
-rw-r--r-- | doc/reading-heap.texi | 136 | ||||
-rw-r--r-- | reading-heap/media.scm | 2 | ||||
-rw-r--r-- | reading-heap/zmq.scm | 73 | ||||
-rwxr-xr-x | scripts/rh-client.in | 28 | ||||
-rwxr-xr-x | scripts/rh-server.in | 16 |
5 files changed, 205 insertions, 50 deletions
diff --git a/doc/reading-heap.texi b/doc/reading-heap.texi index 5e2735a..d1f2557 100644 --- a/doc/reading-heap.texi +++ b/doc/reading-heap.texi @@ -2,15 +2,15 @@ @c -*-texinfo-*- @c %**start of header -@setfilename reading-heap.info +@setfilename guile-reading-heap.info @documentencoding UTF-8 -@settitle Reading-Heap Reference Manual +@settitle Reading Heap Reference Manual @c %**end of header @include version.texi @copying -Copyright @copyright{} 2023 Christopher R. Nelson +Copyright @copyright{} 2024 Christopher R. Nelson Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -22,11 +22,11 @@ Documentation License''. @dircategory The Algorithmic Language Scheme @direntry -* Reading-Heap: (reading-heap). +* Reading Heap: (guile-reading-heap). Manage your heap of to-consume media. @end direntry @titlepage -@title The Reading-Heap Manual +@title The Guile Reading Heap Manual @author Christopher R. Nelson @page @@ -40,21 +40,133 @@ Edition @value{EDITION} @* @contents @c ********************************************************************* -@node Top -@top Reading-Heap +@node Top, Introduction, (dir), (dir) +@top Reading Heap -This document describes Reading-Heap version @value{VERSION}. +This document describes Reading Heap version @value{VERSION}. @menu -* Introduction:: Why Reading-Heap? +* Introduction:: What is Reading-Heap? +* Installation:: How to install Reading-Heap? +* Quickstart:: Getting Started +* Client Subcommands:: How to operate the client + +* Contributing:: Contributing to the Reading Heap project +* Acknowledgments:: Thanks! @end menu @c ********************************************************************* -@node Introduction +@node Introduction, Installation, Top, Top @chapter Introduction -INTRODUCTION HERE +What is Reading Heap? It's a @emph{heap} of things you want to +@emph{read}. Shocking, I know. But what does that mean? Simply, it +means you add a priority when you put an item on the heap, and when +you ask the heap what to read next, it will take your priorities into +account and provide you one of the most important entries as a +suggestion. + +How does this improve on the reading list you have taped to your +refrigerator? Primarily by removing the cognitive burden on choosing +what's next. It also lets you specify that, for instance, you have in +your head you want to read ``Battlefield Earth'', but it's really more +of a sometime before you die thing. You give it the appropriate +priority, and it won't clutter your heap when what you really should +be reading about @uref{https://spritely.institute/hoot, Hoot +WebAssembly}. + +@c ********************************************************************* +@node Installation, Quickstart, Introduction, Top +@chapter Installation + +First, check your favorite package manager. Reading Heap will likely +not be there, but it's the best way to acquire end-user software and +should be a first port of call. + +If (when) that fails, you can continue with the Guile Autotools build. + +@heading Using Autotools + +Installing Reading Heap should be as easy as: +@enumerate +@item +Install the dependencies: +@itemize +@item +autoconf +@item +automake +@item +pkg-config +@item +guile +@item +texinfo +@item +guile-config +@item +guile-json +@item +guile-simple-zmq +@item +zeromq +@end itemize +@item +Run @code{autoreconf -vif && ./configure && make && sudo make install} +@end enumerate + +Exactly how you install the dependencies will depend on your distro. +While installing Guile libraries using autotools you will need to +augment the @env{GUILE_LOAD_PATH} and the +@env{GUILE_LOAD_COMPILED_PATH} environment variables to ensure that +the installed code will be available to Guile & Guile applications. +You could accomplish this by adding the following to your shell of +choice's startup files (for example, .bash_profile or .zshrc) + +@example + +export GUILE_LOAD_PATH=/usr/local/share/guile/site/3.0/ +export GUILE_LOAD_COMPILED_PATH=/usr/local/lib/guile/3.0/site-ccache/ +export PATH=/usr/local/bin/:$PATH + +@end example -This documentation is a stub. +@c ********************************************************************* +@node Quickstart, Client Subcommands, Installation, Top +@chapter Quickstart + +To get quickly started, run the command @command{rh-server --write} + +@c ********************************************************************* +@node Client Subcommands, Contributing, Quickstart, Top +@chapter Client Subcommands + +Reading Heap is sub-divided into different subcommands designed to achieve +specific tasks. You can pass the @option{--help} switch to any of the +subcommands to get concise documentation. + +@c ********************************************************************* +@node Contributing, Acknowledgments, Client Subcommands, Top +@chapter Contributing + +Reading Heap is an open project and we actively invite contribution. +Get in touch with the project on +@email{christopher.nelson@@languidnights.com} or on the +@uref{https://codeberg.org/languidnights/reading-heap, the project +forge page}. The project welcomes ideas, bug reports, patches, or +feedback. + +@c ********************************************************************* +@node Acknowledgments, , Contributing, Top +@chapter Acknowledgments + +Reading Heap would be impossible without the input of various people. +Much of the technical details were ``borrowed'' from guile-hall and +guile-config. The +@uref{https://www.gnu.org/software/guile/manual/index.html, Guile +Manual} is a quite well-written, if occasionally dense, source of +information on some of the thornier issues. And +@uref{https://systemcrafters.net, the System Crafters community} +helped some confidence issues I was having :-) @bye diff --git a/reading-heap/media.scm b/reading-heap/media.scm index a4ffad4..01d2aab 100644 --- a/reading-heap/media.scm +++ b/reading-heap/media.scm @@ -27,6 +27,8 @@ (json->media (call-with-input-file filename get-string-all))) (define (filetree->media-list dirname) + (when (not (access? dirname X_OK)) + (mkdir dirname)) (define (enter? name stat result) (not (member (basename name) '(".git" ".svn" "archive")))) (define (leaf name stat result) diff --git a/reading-heap/zmq.scm b/reading-heap/zmq.scm index 65cf60e..9635fad 100644 --- a/reading-heap/zmq.scm +++ b/reading-heap/zmq.scm @@ -11,38 +11,61 @@ (define (server-setup sock) (zmq-bind-socket server-socket sock)) +(define (rh-server-next heap) + (cond ((heap-empty? heap) + (zmq-send server-socket "no media in queue\n")) + (#t (zmq-send server-socket (string-append + (media->json (heap-get-min heap)) + "\n"))))) + +(define (rh-server-new heap write-location) + (zmq-send server-socket "ok\n") + (let* ((media-raw (zmq-receive server-socket 1500)) + (media (json->media media-raw)) + (heap-new (heap-insert (media-priority media) + media + heap))) + (call-with-output-file (string-append + write-location + "/" + (media-title media)) + (lambda (port) + (display media-raw port))) + (zmq-send server-socket (string-append + (media-title media) + " added\n")) + heap-new)) + +(define (rh-server-consume heap write-location archive-location) + (let ((media (cond ((heap-empty? heap) "no media in queue\n") + (#t (heap-get-min heap)))) + (heap-new (cond ((heap-empty? heap) heap) + (#t (heap-delete-min heap))))) + (when (not (access? archive-location X_OK)) + (mkdir archive-location)) + (rename-file (string-append write-location + "/" + (media-title media)) + (string-append archive-location + "/" + (media-title media))) + heap-new)) + (define (rh-receive heap write-location archive-location) (let ((command (zmq-receive server-socket 1500))) (cond ((string= command "next") - (cond ((heap-empty? heap) - (zmq-send server-socket "no media in queue")) - (#t (zmq-send server-socket (media->json (heap-get-min heap))))) + (rh-server-next heap) (rh-receive heap write-location archive-location)) ((string= command "new") - (zmq-send server-socket "ok") - (let* ((media-raw (zmq-receive server-socket 1500)) - (media-data (json->media media-raw)) - (heap-new (heap-insert (media-priority media-data) media-data heap))) - (call-with-output-file (string-append write-location - "/" - (media-title media-data)) - (lambda (port) - (display media-raw port))) - (zmq-send server-socket "ok") + (let ((heap-new (rh-server-new heap write-location))) (rh-receive heap-new write-location archive-location))) ((string= command "consume") - (let ((media (cond ((heap-empty? heap) "no media in queue") - (#t (heap-get-min heap)))) - (heap-new (cond ((heap-empty? heap) heap) - (#t (heap-delete-min heap))))) - (rename-file (string-append write-location - "/" - (media-title media)) - (string-append archive-location - "/" - (media-title media))) - (zmq-send server-socket "ok") - (rh-receive heap-new write-location archive-location)))))) + (let ((heap-new (rh-server-consume heap write-location archive-location))) + (rh-receive heap-new write-location archive-location))) + ((string= command "shutdown") + (zmq-send server-socket "shutting down rh-server\n")) + (#t (rh-server-next heap) + (rh-receive heap write-location archive-location))))) (export rh-receive server-setup) diff --git a/scripts/rh-client.in b/scripts/rh-client.in index 64dfde6..8c96acb 100755 --- a/scripts/rh-client.in +++ b/scripts/rh-client.in @@ -1,4 +1,5 @@ -#!/usr/bin/env guile +#!@GUILE@ \ +--no-auto-compile -e main -s !# (use-modules (simple-zmq) (config) @@ -28,19 +29,19 @@ (switch (name 'title) (synopsis "title of the new media") - (default "Foundation Trilogy") + (default "") (test string?) (character #t)) (switch (name 'author) (synopsis "author of the new media") - (default "Isaac Asimov") + (default "") (test string?) (character #t)) (switch (name 'location) (synopsis "location of the new media") - (default "https://openlibrary.org/books/OL20930675M/The_foundation_trilogy") + (default "") (test string?) (character #t)) (switch @@ -62,6 +63,10 @@ (configuration (name 'consume) (synopsis "remove the next media from the heap") + (wanted '((keywords . (service-socket))))) + (configuration + (name 'shutdown) + (synopsis "shutdown the heap") (wanted '((keywords . (service-socket))))))) (directory (list (in-home ".reading-heap/") (path (given @@ -70,7 +75,11 @@ "/.config")) "/reading-heap/")) (eager? #t)))) - (parser sexp-parser))) + (parser sexp-parser) + (copyright @COPYRIGHT@) + (version @HVERSION@) + (license @LICENSE@) + (author @AUTHOR@))) (define context (zmq-create-context)) @@ -78,7 +87,7 @@ (define (client-setup sock) (zmq-connect client-socket sock)) - + (define (rh-client-next) (zmq-send client-socket "next") (let ((msg (zmq-receive-bytevector client-socket 1500))) @@ -96,6 +105,10 @@ (zmq-send client-socket "consume") (display (zmq-receive client-socket 1500))) +(define (rh-client-shutdown) + (zmq-send client-socket "shutdown") + (display (zmq-receive client-socket 1500))) + (define (json-from-args priority title author location) (scm->json-string `(("priority" . ,priority) ("title" . ,title) @@ -118,6 +131,9 @@ ((string=? (cadr (full-command options)) "consume") (client-setup (option-ref options 'service-socket)) (rh-client-consumed)) + ((string=? (cadr (full-command options)) "shutdown") + (client-setup (option-ref options 'service-socket)) + (rh-client-shutdown)) (#t (emit-help options))))) (main (command-line)) diff --git a/scripts/rh-server.in b/scripts/rh-server.in index 9749ec2..a9dd758 100755 --- a/scripts/rh-server.in +++ b/scripts/rh-server.in @@ -1,4 +1,5 @@ -#!/usr/bin/env guile +#!@GUILE@ \ +--no-auto-compile -e main -s !# (use-modules (srfi srfi-1) (config) @@ -38,7 +39,7 @@ (character #f)) (switch (name 'serve) - (synopsis "server the media heap") + (synopsis "serve the media heap") (default #f) (test boolean?) (character #t)) @@ -51,16 +52,17 @@ "/reading-heap/")) (eager? #t)))) (parser sexp-parser) - (copyright '(2023)) - (version "0.1") - (license agpl3+) - (author "Christopher R. Nelson"))) + (copyright @COPYRIGHT@) + (version @HVERSION@) + (license @LICENSE@) + (author @AUTHOR@))) (define (main cmd-line) (let ((options (getopt-config-auto cmd-line config))) (when (option-ref options 'write) (options-write options)) - (when (option-ref options 'serve) + (when (or (option-ref options 'serve) + (not (option-ref options 'write))) (let* ((media (filetree->media-list (option-ref options 'media-library))) (priorities (map media-priority media)) (heap (fold heap-insert 'E priorities media))) |