changeset 609:7bda01659426 rust

not building, paramwaiter work
author Matt Johnston <matt@ucc.asn.au>
date Sat, 18 Feb 2017 00:21:10 +0800
parents 71f045231a07
children af0dac00d40b
files rust/Cargo.lock rust/Cargo.toml rust/src/fridge.rs rust/src/main.rs rust/src/paramwaiter.rs rust/src/sensor.rs rust/src/types.rs
diffstat 7 files changed, 202 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/rust/Cargo.lock	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/Cargo.lock	Sat Feb 18 00:21:10 2017 +0800
@@ -2,10 +2,11 @@
 name = "wort-templog"
 version = "0.1.0"
 dependencies = [
+ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures-cpupool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -15,7 +16,8 @@
  "serde_derive 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.2.1 (git+https://github.com/alexcrichton/toml-rs?branch=serde-upgrade)",
+ "tokio-curl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -45,6 +47,31 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "curl"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "curl-sys"
+version = "0.3.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "docopt"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -74,7 +101,7 @@
 
 [[package]]
 name = "futures-cpupool"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -83,6 +110,20 @@
 ]
 
 [[package]]
+name = "gcc"
+version = "0.3.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "gdi32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "kernel32-sys"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -107,6 +148,16 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "libz-sys"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "log"
 version = "0.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -174,6 +225,28 @@
 ]
 
 [[package]]
+name = "openssl-probe"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "quote"
 version = "0.3.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -336,9 +409,26 @@
 ]
 
 [[package]]
+name = "tokio-curl"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mio 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "toml"
-version = "0.2.1"
-source = "git+https://github.com/alexcrichton/toml-rs?branch=serde-upgrade#32a0a67b8de1d0b2a0dd98f1c96087fc9109fd00"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -357,6 +447,15 @@
 ]
 
 [[package]]
+name = "user32-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "utf8-ranges"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -395,14 +494,19 @@
 "checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
+"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
+"checksum curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d909dc402ae80b6f7b0118c039203436061b9d9a3ca5d2c2546d93e0a61aaa"
 "checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum futures 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c1913eb7083840b1bbcbf9631b7fda55eaf35fe7ead13cca034e8946f9e2bc41"
-"checksum futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bb982bb25cd8fa5da6a8eb3a460354c984ff1113da82bcb4f0b0862b5795db82"
+"checksum futures-cpupool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e48a3fff6a58fe9df1eed13d2599650416a987386c43a19aec656c3e6a2c229"
+"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
+"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
+"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
@@ -410,6 +514,9 @@
 "checksum miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a78d2605eb97302c10cf944b8d96b0a2a890c52957caf92fcd1f24f69049579"
 "checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2"
 "checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
+"checksum openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "756d49c8424483a3df3b5d735112b4da22109ced9a8294f1f5cdf80fb3810919"
+"checksum openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5dd48381e9e8a6dce9c4c402db143b2e243f5f872354532f7a009c289b3998ca"
+"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum quote 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b44fd83db28b83c1c58187159934906e5e955c812e211df413b76b03c909a5"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "checksum redox_syscall 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd35cc9a8bdec562c757e3d43c1526b5c6d2653e23e2315065bc25556550753"
@@ -431,9 +538,11 @@
 "checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d"
 "checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
 "checksum tokio-core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3d1be481b55126f02ef88ff86748086473cb537a949fc4a8f4be403a530ae54b"
-"checksum toml 0.2.1 (git+https://github.com/alexcrichton/toml-rs?branch=serde-upgrade)" = "<none>"
+"checksum tokio-curl 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "abc816085f1fe81e04960a50e53a49ac9d2f5b0263c3e52430ad98f77f725f2a"
+"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
+"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
 "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
--- a/rust/Cargo.toml	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/Cargo.toml	Sat Feb 18 00:21:10 2017 +0800
@@ -17,8 +17,6 @@
 time = "0.1"
 lazy_static = "0.2"
 regex = "0.2"
-
-[dependencies.toml]
-git = "https://github.com/alexcrichton/toml-rs"
-branch = "serde-upgrade"
-features = [ "serde" ]
+tokio-curl = "0.1"
+toml = "0.3"
+curl = "0.4"
--- a/rust/src/fridge.rs	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/src/fridge.rs	Sat Feb 18 00:21:10 2017 +0800
@@ -68,7 +68,7 @@
             wort_valid_time: Instant::now() - Duration::new(config.FRIDGE_WORT_INVALID_TIME, 100),
         };
         if nowait {
-            f.last_off_time -= Duration::new(config.FRIDGE_DELAY, 100);
+            f.last_off_time -= Duration::new(config.FRIDGE_DELAY, 1);
         }
         f.tick();
         f
@@ -125,15 +125,13 @@
         self.handle.spawn(t);
     }
 
-    fn process_msg(&mut self, msg: Message)
-            -> Box<Future<Item=(), Error=()>> {
+    fn process_msg(&mut self, msg: Message) {
         debug!("process_msg {:?}", msg);
         match msg {
             Message::Sensor{wort, fridge} => self.update_sensor(wort, fridge),
             Message::Params(p) => self.update_params(p),
             Message::Tick(v) => if v == self.ticker {self.tick()}, // schedule a timeout if there are none pending
         };
-        future::ok::<(),()>(()).boxed()
     }
 
     pub fn update_params(&mut self, p: Params) {
--- a/rust/src/main.rs	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/src/main.rs	Sat Feb 18 00:21:10 2017 +0800
@@ -5,6 +5,8 @@
 extern crate env_logger;
 extern crate rustc_serialize;
 extern crate time;
+extern crate tokio_curl;
+extern crate curl;
 
 #[macro_use] 
 extern crate lazy_static;
@@ -18,9 +20,6 @@
 extern crate docopt;
 
 use std::io;
-use std::time::{Duration,Instant};
-use std::ops::Not;
-use std::cell::Cell;
 
 use tokio_core::reactor::Core;
 use futures::{Stream,Sink,Future};
@@ -29,7 +28,7 @@
 
 mod config;
 mod sensor;
-pub mod fridge;
+mod fridge;
 mod types;
 mod paramwaiter;
 
@@ -175,28 +174,3 @@
 
     run(&config, args.flag_nowait, args.flag_test);
 }
-
-/// Call closures with a rate limit. Useful for log message ratelimiting
-pub struct NotTooOften {
-    last: Cell<Instant>,
-    limit: Duration,
-}
-
-impl NotTooOften {
-    pub fn new(limit_secs: u64) -> Self {
-        NotTooOften {
-            limit: Duration::new(limit_secs, 0),
-            last: Cell::new(Instant::now() - Duration::new(limit_secs+1, 0)),
-        }
-    }
-
-    pub fn and_then<F>(&self, op: F)
-        where F: Fn() {
-        let now = Instant::now();
-        if now - self.last.get() > self.limit {
-            self.last.set(now);
-            op();
-        }
-    }
-}
-
--- a/rust/src/paramwaiter.rs	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/src/paramwaiter.rs	Sat Feb 18 00:21:10 2017 +0800
@@ -7,30 +7,63 @@
 
 use tokio_core::reactor::Interval;
 use tokio_core::reactor::Handle;
-use futures::Stream;
+use tokio_curl::Session;
+use futures::{Stream,Future,future};
 use types::*;
+use curl::Easy;
+use ::Config;
 
 pub struct ParamWaiter {
+    limitlog: NotTooOften,
+    epoch_tag: String,
+    session: Option<Session>,
+    config: Config,
 }
 
+const LOGMINUTES: u64 = 15;
+
 impl ParamWaiter {
-    fn step(&mut self) -> Params {
+    pub fn new(config: &Config) -> Self {
+        ParamWaiter {
+            limitlog: NotTooOften::new(LOGMINUTES*60),
+            epoch_tag: String::new(),
+            session: None,
+            config: config.clone(),
+        }
+    }
+
+    fn make_req(&self) -> Easy {
+        let mut req = Easy::new();
+        req.get(true).unwrap();
+        req.url(config.SETTINGS_URL);
+    }
+
+    fn step(&mut self, handle: &Handle) -> Box<Future<Item=Option<Params>, Error=io::Error>> {
+        if self.session.is_none() {
+            self.session = Some(Session::new(handle.clone()))
+        }
+
+        let req = self.make_req();
+        /*
+        self.session.unwrap().perform(self.make_req())
+            .and_then(||)
+            */
+
         let mut p = Params::defaults();
         p.fridge_setpoint = 17.0 + 4.0*rand::random::<f32>();
-        p
-    }
-
-    pub fn new() -> Self {
-        ParamWaiter {}
+        future::ok(p).boxed()
     }
 
-    pub fn stream(handle: &Handle) -> Box<Stream<Item=Params, Error=io::Error>> {
-        let mut s = ParamWaiter::new();
+    pub fn stream(&mut self, handle: &Handle) -> Box<Stream<Item=Params, Error=io::Error>> {
 
         let dur = Duration::from_millis(4000);
-        Interval::new(dur, handle).unwrap().map(move |()| {
-            s.step()
-        }).boxed()
+        let i = Interval::new(dur, handle).unwrap()
+            .and_then(move |()| {
+                s.step()
+            })
+            // throw away None params
+            .filter_map(|p| p);
+        Box::new(i)
     }
 }
 
--- a/rust/src/sensor.rs	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/src/sensor.rs	Sat Feb 18 00:21:10 2017 +0800
@@ -72,6 +72,7 @@
     }
 
     fn sensor_names(&self) -> Result<Vec<String>, Box<Error>> {
+        // TODO: needs to handle multiple busses.
         let mut path = PathBuf::from(&self.config.SENSOR_BASE_DIR);
         path.push("w1_master_slaves");
 
--- a/rust/src/types.rs	Fri Feb 17 23:07:33 2017 +0800
+++ b/rust/src/types.rs	Sat Feb 18 00:21:10 2017 +0800
@@ -1,7 +1,8 @@
 use std::collections::HashMap;
-use std::time::Duration;
+use std::time::{Duration,Instant};
 use std::error::Error;
 use std::fmt;
+use std::cell::Cell;
 
 use serde::{Deserialize,Serialize};
 
@@ -35,7 +36,7 @@
 #[derive(Debug)]
 pub struct ParamHolder {
     pub p: Params,
-    epoch: String, // XXX or a byte array?
+    epoch: String,
 }
 
 impl ParamHolder {
@@ -45,6 +46,11 @@
             epoch: String::new(),
         }
     }
+
+    pub fn receive(&mut self, p: &Params, epoch: &String)
+    {
+
+    }
 }
 
 #[derive(Debug)]
@@ -96,4 +102,28 @@
 }
 
 
+/// Call closures with a rate limit. Useful for log message ratelimiting
+pub struct NotTooOften {
+    last: Cell<Instant>,
+    limit: Duration,
+}
 
+impl NotTooOften {
+    pub fn new(limit_secs: u64) -> Self {
+        NotTooOften {
+            limit: Duration::new(limit_secs, 0),
+            last: Cell::new(Instant::now() - Duration::new(limit_secs+1, 0)),
+        }
+    }
+
+    pub fn and_then<F>(&self, op: F)
+        where F: Fn() {
+        let now = Instant::now();
+        if now - self.last.get() > self.limit {
+            self.last.set(now);
+            op();
+        }
+    }
+}
+
+