From 36d8fa1273bb0cecf360606201b03e2b53ed613d Mon Sep 17 00:00:00 2001 From: Simon Brooke Date: Wed, 29 Mar 2017 06:10:07 +0100 Subject: [PATCH] #13: Beginning work on outbound queue --- src/cljc/youyesyet/outqueue.cljc | 115 +++++++++++++++++++++++++ src/cljs/youyesyet/db.cljs | 2 + src/cljs/youyesyet/subscriptions.cljs | 5 ++ src/cljs/youyesyet/views/about.cljs | 2 +- src/cljs/youyesyet/views/electors.cljs | 10 ++- 5 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 src/cljc/youyesyet/outqueue.cljc diff --git a/src/cljc/youyesyet/outqueue.cljc b/src/cljc/youyesyet/outqueue.cljc new file mode 100644 index 0000000..f2f0df3 --- /dev/null +++ b/src/cljc/youyesyet/outqueue.cljc @@ -0,0 +1,115 @@ +(ns youyesyet.outqueue + (:require + #?(:clj [clojure.core] + :cljs [reagent.core :refer [atom]]))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; +;;;; youyesyet.outqueue: queue of messages waiting to be sent to the server. +;;;; +;;;; This program is free software; you can redistribute it and/or +;;;; modify it under the terms of the GNU General Public License +;;;; as published by the Free Software Foundation; either version 2 +;;;; of the License, or (at your option) any later version. +;;;; +;;;; This program is distributed in the hope that it will be useful, +;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;;; GNU General Public License for more details. +;;;; +;;;; You should have received a copy of the GNU General Public License +;;;; along with this program; if not, write to the Free Software +;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +;;;; USA. +;;;; +;;;; Copyright (C) 2016 Simon Brooke for Radical Independence Campaign +;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; The items are (obviously) the actual items in the queue; +;;; the queue is locked if an attempt is currently being made to transmit +;;; an item. + +(defn new-queue + "Create a new queue" + ([] + (new-queue '())) + ([items] + (atom {:locked false + :items (if + (seq? items) + (reverse items) + (list items))}))) + +(defn add! + "Add this item to the queue." + [q item] + (swap! q + (fn [a] + (assoc a :items + (cons item (:items a)))))) + +(defn q? + [x] + (try + (let [q (deref x) + locked (:locked q)] + (and + (seq? (:items q)) + (or (true? locked) (false? locked)))) + (catch #?(:clj Exception :cljs js/Object) any + #?(:clj (print (.getMessage any)) + :cljs (js/console.log (str any)))))) + +(defn peek + "Look at the next item which could be removed from the queue." + [q] + (last (:items (deref q)))) + +(defn locked? + [q] + (:locked (deref q))) + +(defn unlock! + ([q ] + (unlock! q true)) + ([q value] + (swap! q (fn [a] (assoc a :locked (not (true? value))))))) + +(defn lock! + [q] + (unlock! q false)) + + +(defn count + "Return the count of items currently in the queue." + [q] + (count (deref q))) + +(defn take! + "Return the first item from the queue, rebind the queue to the remaining + items. If the queue is empty return nil." + [q] + (swap! q (fn [a] + (let [items (reverse (:items a)) + item (first items) + new-queue (reverse (rest items))] + (assoc (assoc a :items new-queue) :v item)))) + (:v (deref q))) + +(defn maybe-process-next + "Apply this process, assumed to be a function of one argument, to the next + item in the queue, if the queue is not currently locked; return the value + returned by process." + [q process] + (if (and (q? q)(not (locked? q))) + (try + (lock! q) + (let [v (apply process (list (peek q)))] + (take! q) + v) + (catch #?(:clj Exception :cljs js/Object) any + #?(:clj (print (.getMessage any)) + :cljs (js/console.log (str any)))) + (finally (unlock! q))) + )) diff --git a/src/cljs/youyesyet/db.cljs b/src/cljs/youyesyet/db.cljs index 754ec45..19a9e4a 100644 --- a/src/cljs/youyesyet/db.cljs +++ b/src/cljs/youyesyet/db.cljs @@ -58,6 +58,8 @@ :motd "This is a test version only. There is no real data." ;;; the options from among which electors can select. :options [{:id :yes :description "Yes"} {:id :no :description "No"}] + ;;; the number of requests created by the user in the current session + :requests 0 ;;; the currently displayed 'page' within the app. :page :home }) diff --git a/src/cljs/youyesyet/subscriptions.cljs b/src/cljs/youyesyet/subscriptions.cljs index d31e1a3..d6961cf 100644 --- a/src/cljs/youyesyet/subscriptions.cljs +++ b/src/cljs/youyesyet/subscriptions.cljs @@ -39,6 +39,11 @@ (fn [db _] (:addresses db))) +(reg-sub + :changes + (fn [db _] + (:changes db))) + (reg-sub :elector (fn [db _] diff --git a/src/cljs/youyesyet/views/about.cljs b/src/cljs/youyesyet/views/about.cljs index 966e000..cd49d43 100644 --- a/src/cljs/youyesyet/views/about.cljs +++ b/src/cljs/youyesyet/views/about.cljs @@ -5,7 +5,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; -;;;; youyesyet.views.electors: about/credits view for youyesyet. +;;;; youyesyet.views.about: about/credits view for youyesyet. ;;;; ;;;; This program is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU General Public License diff --git a/src/cljs/youyesyet/views/electors.cljs b/src/cljs/youyesyet/views/electors.cljs index 01a37a7..f6cc8d4 100644 --- a/src/cljs/youyesyet/views/electors.cljs +++ b/src/cljs/youyesyet/views/electors.cljs @@ -1,5 +1,6 @@ (ns youyesyet.views.electors - (:require [re-frame.core :refer [reg-sub subscribe]] + (:require [reagent.core :refer [atom]] + [re-frame.core :refer [reg-sub subscribe]] [youyesyet.ui-utils :as ui])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -47,12 +48,14 @@ image (if gender (name gender) "unknown")] [:td {:key (:id elector)} [:img {:src (str "img/gender/" image ".png") :alt image}]])) + (defn genders-row [electors] [:tr (map #(gender-cell %) electors)]) + (defn name-cell [elector] [:td {:key (str "name-" (:id elector))} (:name elector)]) @@ -63,6 +66,7 @@ (map #(name-cell %) electors)]) + (defn options-row [electors option] (let [optid (:id option) @@ -77,6 +81,7 @@ [:img {:src image :alt optname}]]]) electors)])) + (defn issue-cell "Create an issue cell for a particular elector" [elector] @@ -98,7 +103,8 @@ (let [address @(subscribe [:address]) addresses @(subscribe [:addresses]) electors (:electors address) - options @(subscribe [:options])] + options @(subscribe [:options]) + changes @(subscribe [:changes])] (if address [:div [:h1 (:address address)]