Skip to content

Commit 6aec260

Browse files
committed
Improve & Test expiration
1 parent 5d69d80 commit 6aec260

File tree

4 files changed

+63
-17
lines changed

4 files changed

+63
-17
lines changed

src/document.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl Database {
236236
}
237237
}
238238

239-
/// Returns the time, if any, at which a given document will expire and be purged.
239+
/// Returns the time, if any, at which a given document will expire and be purged in milliseconds since the Unix epoch (1/1/1970.).
240240
/// Documents don't normally expire; you have to call `set_document_expiration`
241241
/// to set a document's expiration time.
242242
#[deprecated(note = "please use `document_expiration` on default collection instead")]
@@ -250,7 +250,7 @@ impl Database {
250250
);
251251
match exp {
252252
0 => Ok(None),
253-
_ if exp > 0 => Ok(Some(Timestamp(exp))),
253+
_ if exp > 0 => Ok(Some(Timestamp::new(exp))),
254254
_ => failure(error),
255255
}
256256
}
@@ -260,7 +260,7 @@ impl Database {
260260
#[deprecated(note = "please use `set_document_expiration` on default collection instead")]
261261
pub fn set_document_expiration(&mut self, doc_id: &str, when: Option<Timestamp>) -> Result<()> {
262262
let exp: i64 = match when {
263-
Some(Timestamp(n)) => n,
263+
Some(Timestamp { timestamp }) => timestamp,
264264
_ => 0,
265265
};
266266
unsafe {
@@ -448,7 +448,7 @@ impl Collection {
448448
}
449449
}
450450

451-
/// Returns the time, if any, at which a given document will expire and be purged.
451+
/// Returns the time, if any, at which a given document will expire and be purged in milliseconds since the Unix epoch (1/1/1970.).
452452
/// Documents don't normally expire; you have to call set_document_expiration
453453
/// to set a document's expiration time.
454454
pub fn document_expiration(&self, doc_id: &str) -> Result<Option<Timestamp>> {
@@ -461,16 +461,16 @@ impl Collection {
461461
);
462462
match exp {
463463
0 => Ok(None),
464-
_ if exp > 0 => Ok(Some(Timestamp(exp))),
464+
_ if exp > 0 => Ok(Some(Timestamp::new(exp))),
465465
_ => failure(error),
466466
}
467467
}
468468
}
469469

470-
/// Sets or clears the expiration time of a document.
470+
/// Sets or clears the expiration time of a document in milliseconds since the Unix epoch (1/1/1970.).
471471
pub fn set_document_expiration(&mut self, doc_id: &str, when: Option<Timestamp>) -> Result<()> {
472472
let exp: i64 = match when {
473-
Some(Timestamp(n)) => n,
473+
Some(Timestamp { timestamp }) => timestamp,
474474
_ => 0,
475475
};
476476
unsafe {

src/fleece.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ impl Value {
291291
if t == 0 {
292292
return None;
293293
}
294-
Some(Timestamp(t))
294+
Some(Timestamp::new(t))
295295
}
296296
}
297297

src/lib.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ mod c_api;
5454

5555
use self::c_api::{
5656
CBLListenerToken, CBLRefCounted, CBL_DumpInstances, CBL_InstanceCount, CBL_Release, CBL_Retain,
57-
CBLListener_Remove, CBLITE_VERSION,
57+
CBLListener_Remove, CBL_Now, CBLITE_VERSION,
5858
};
5959
#[cfg(target_os = "android")]
6060
use self::c_api::{CBLError, CBLInitContext, CBL_Init};
61-
use std::ffi::CStr;
61+
use std::{ffi::CStr, time::Duration};
6262

6363
//////// RE-EXPORT:
6464

@@ -78,9 +78,32 @@ pub trait CblRef {
7878
fn get_ref(&self) -> Self::Output;
7979
}
8080

81-
#[derive(Debug, Clone, Copy)]
81+
#[derive(Debug, Clone, Copy, PartialEq)]
8282
/// A time value for document expiration. Defined as milliseconds since the Unix epoch (1/1/1970.)
83-
pub struct Timestamp(pub i64);
83+
pub struct Timestamp {
84+
pub(crate) timestamp: i64,
85+
}
86+
87+
impl Timestamp {
88+
pub fn now() -> Timestamp {
89+
Timestamp {
90+
timestamp: unsafe { CBL_Now() },
91+
}
92+
}
93+
94+
/// Create a Timestamp from milliseconds since the Unix epoch (1/1/1970.)
95+
pub(crate) fn new(milliseconds_from_epoch: i64) -> Self {
96+
Timestamp {
97+
timestamp: milliseconds_from_epoch,
98+
}
99+
}
100+
101+
pub fn add(&self, duration: Duration) -> Self {
102+
Timestamp {
103+
timestamp: self.timestamp + duration.as_millis() as i64,
104+
}
105+
}
106+
}
84107

85108
pub struct Listener<T> {
86109
pub listener_token: ListenerToken,

tests/document_tests.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ extern crate core;
22
extern crate couchbase_lite;
33

44
use self::couchbase_lite::*;
5-
use std::time::Duration;
5+
use std::{thread::sleep, time::Duration};
66
use utils::{init_logging, LeakChecker};
77

88
pub mod utils;
@@ -296,12 +296,35 @@ fn database_document_expiration() {
296296
let mut document = Document::new_with_id("foo");
297297
db.save_document_with_concurency_control(&mut document, ConcurrencyControl::FailOnConflict)
298298
.expect("save_document");
299+
300+
// No expiration by default
299301
let expiration = db.document_expiration("foo").expect("document_expiration");
300302
assert!(expiration.is_none());
301-
db.set_document_expiration("foo", Some(Timestamp(1000000000)))
303+
304+
// Set expiration in 2 seconds
305+
let expiration = Timestamp::now().add(Duration::from_secs(2));
306+
db.set_document_expiration("foo", Some(expiration))
302307
.expect("set_document_expiration");
303-
let expiration = db.document_expiration("foo").expect("document_expiration");
304-
assert!(expiration.is_some());
305-
assert_eq!(expiration.unwrap().0, 1000000000);
308+
309+
// Check expiration is set up
310+
let doc_expiration = db.document_expiration("foo").expect("document_expiration");
311+
assert_eq!(doc_expiration.unwrap(), expiration);
312+
313+
// Check the document is still present after 1 second
314+
sleep(Duration::from_secs(1));
315+
assert!(db.get_document("foo").is_ok());
316+
317+
// Move to expiration time
318+
sleep(Duration::from_secs(1));
319+
320+
// Check documents disappears
321+
for _ in 0..5 {
322+
if db.get_document("foo").unwrap().is_deleted() {
323+
return;
324+
}
325+
326+
sleep(Duration::from_secs(1));
327+
}
328+
panic!("The document is still present 10 seconds after its expiration time");
306329
});
307330
}

0 commit comments

Comments
 (0)