From a9f6fc2681f5574cdd4840cebe208277c6887a83 Mon Sep 17 00:00:00 2001 From: Ben Bangert Date: Tue, 1 May 2018 08:10:38 -0700 Subject: [PATCH] feat: port check storage command into Rust Co-authored by: Phil Jenvey Some components of CheckStorage are left in Python as they're used by the delete tests. Closes #1189 --- autopush/tests/test_rs_integration.py | 6 +- autopush/tests/test_webpush_server.py | 69 ---- autopush/webpush_server.py | 2 - autopush_rs/Cargo.lock | 346 ++++++++++-------- autopush_rs/Cargo.toml | 7 +- autopush_rs/src/call.rs | 31 -- autopush_rs/src/client.rs | 63 +--- autopush_rs/src/errors.rs | 4 + autopush_rs/src/lib.rs | 4 + autopush_rs/src/protocol.rs | 2 +- autopush_rs/src/server/mod.rs | 14 +- autopush_rs/src/util/ddb_helpers.rs | 507 +++++++++++++++++++++++++- 12 files changed, 722 insertions(+), 333 deletions(-) diff --git a/autopush/tests/test_rs_integration.py b/autopush/tests/test_rs_integration.py index a2fb557c..ffdbc27f 100644 --- a/autopush/tests/test_rs_integration.py +++ b/autopush/tests/test_rs_integration.py @@ -231,10 +231,8 @@ def test_hello_only_has_three_calls(self): result = yield client.hello() assert result != {} assert result["use_webpush"] is True - yield client.wait_for(lambda: len(db.DB_CALLS) == 4) - assert db.DB_CALLS == ['register_user', 'register_user', - 'fetch_messages', - 'fetch_timestamp_messages'] + yield client.wait_for(lambda: len(db.DB_CALLS) == 2) + assert db.DB_CALLS == ['register_user', 'register_user'] db.DB_CALLS = [] db.TRACK_DB_CALLS = False diff --git a/autopush/tests/test_webpush_server.py b/autopush/tests/test_webpush_server.py index cc2afdf3..838ede3b 100644 --- a/autopush/tests/test_webpush_server.py +++ b/autopush/tests/test_webpush_server.py @@ -269,75 +269,6 @@ def test_existing_newer_uaid(self): assert result.uaid is None -class TestCheckStorageProcessor(BaseSetup): - def _makeFUT(self): - from autopush.webpush_server import CheckStorageCommand - return CheckStorageCommand(self.conf, self.db) - - def test_no_messages(self): - p = self._makeFUT() - check = CheckStorageFactory(message_month=self.db.current_msg_month) - result = p.process(check) - assert len(result.messages) == 0 - - def test_five_messages(self): - p = self._makeFUT() - check = CheckStorageFactory(message_month=self.db.current_msg_month) - self._store_messages(check.uaid, num=5) - result = p.process(check) - assert len(result.messages) == 5 - - def test_many_messages(self): - """Test many messages to fill the batches with topics and non-topic - - This is a long test, intended to ensure that all the topic messages - properly come out and set whether to include the topic flag again or - proceed to get non-topic messages. - - """ - p = self._makeFUT() - check = CheckStorageFactory(message_month=self.db.current_msg_month) - self._store_messages(check.uaid, topic=True, num=22) - self._store_messages(check.uaid, num=15) - result = p.process(check) - assert len(result.messages) == 10 - - # Delete all the messages returned - for msg in result.messages: - notif = msg.to_WebPushNotification() - self.db.message.delete_message(notif) - - check.timestamp = result.timestamp - check.include_topic = result.include_topic - result = p.process(check) - assert len(result.messages) == 10 - - # Delete all the messages returned - for msg in result.messages: - notif = msg.to_WebPushNotification() - self.db.message.delete_message(notif) - - check.timestamp = result.timestamp - check.include_topic = result.include_topic - result = p.process(check) - assert len(result.messages) == 2 - - # Delete all the messages returned - for msg in result.messages: - notif = msg.to_WebPushNotification() - self.db.message.delete_message(notif) - - check.timestamp = result.timestamp - check.include_topic = result.include_topic - result = p.process(check) - assert len(result.messages) == 10 - - check.timestamp = result.timestamp - check.include_topic = result.include_topic - result = p.process(check) - assert len(result.messages) == 5 - - class TestDeleteMessageProcessor(BaseSetup): def _makeFUT(self): from autopush.webpush_server import DeleteMessageCommand diff --git a/autopush/webpush_server.py b/autopush/webpush_server.py index b9746a01..c9475659 100644 --- a/autopush/webpush_server.py +++ b/autopush/webpush_server.py @@ -292,7 +292,6 @@ def __init__(self, conf, db): self.store_messages_process = StoreMessagesUserCommand(conf, db) self.deserialize = dict( hello=Hello, - check_storage=CheckStorage, delete_message=DeleteMessage, drop_user=DropUser, migrate_user=MigrateUser, @@ -302,7 +301,6 @@ def __init__(self, conf, db): ) self.command_dict = dict( hello=self.hello_processor, - check_storage=self.check_storage_processor, delete_message=self.delete_message_processor, drop_user=self.drop_user_processor, migrate_user=self.migrate_user_proocessor, diff --git a/autopush_rs/Cargo.lock b/autopush_rs/Cargo.lock index 41a2f881..101a1835 100644 --- a/autopush_rs/Cargo.lock +++ b/autopush_rs/Cargo.lock @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -38,27 +38,30 @@ dependencies = [ name = "autopush" version = "0.1.0" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "cadence 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-backoff 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "hostname 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", "rusoto_core 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "rusoto_dynamodb 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "sentry 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_dynamodb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "slog-async 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-json 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -73,19 +76,19 @@ dependencies = [ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tungstenite 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tungstenite 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "woothee 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -94,13 +97,13 @@ name = "backtrace-sys" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -114,7 +117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -143,7 +146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -160,12 +163,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.10" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -202,7 +205,7 @@ dependencies = [ [[package]] name = "crc" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -228,7 +231,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -240,7 +243,7 @@ name = "crossbeam-utils" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -248,7 +251,7 @@ name = "crossbeam-utils" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -320,15 +323,15 @@ name = "encoding_rs" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.5.7" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -339,7 +342,7 @@ name = "error-chain" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -347,7 +350,7 @@ name = "error-chain" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -378,7 +381,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -432,12 +435,12 @@ name = "heck" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hex" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -476,8 +479,8 @@ name = "hyper" version = "0.11.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -521,7 +524,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -529,7 +532,7 @@ name = "input_buffer" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -603,7 +606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -619,7 +622,7 @@ name = "log" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -654,8 +657,8 @@ version = "2.0.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -696,7 +699,7 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -707,7 +710,7 @@ name = "net2" version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -747,29 +750,29 @@ dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl-sys" -version = "0.9.28" +version = "0.9.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -794,33 +797,33 @@ dependencies = [ [[package]] name = "phf" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -829,12 +832,12 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -852,10 +855,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -893,19 +896,19 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -921,7 +924,7 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -937,7 +940,7 @@ name = "reqwest" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -946,8 +949,8 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -961,9 +964,9 @@ name = "rusoto_core" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -971,8 +974,8 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rusoto_credential 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -988,8 +991,8 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1001,15 +1004,15 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", "rusoto_core 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1027,7 +1030,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "schannel" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1036,7 +1039,7 @@ dependencies = [ [[package]] name = "scoped-tls" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1082,15 +1085,15 @@ name = "sentry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1098,38 +1101,46 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.37" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.37" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.23.0" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_dynamodb" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rusoto_dynamodb 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1139,7 +1150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1150,7 +1161,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "sha2" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1195,8 +1206,8 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1260,11 +1271,11 @@ dependencies = [ [[package]] name = "syn" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1292,7 +1303,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1343,17 +1354,18 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1362,17 +1374,17 @@ name = "tokio-core" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1383,12 +1395,22 @@ dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-fs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-io" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1399,7 +1421,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1447,7 +1469,7 @@ name = "tokio-tcp" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1457,7 +1479,7 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1470,7 +1492,7 @@ dependencies = [ [[package]] name = "tokio-timer" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1503,7 +1525,7 @@ name = "tokio-udp" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1516,9 +1538,9 @@ name = "tungstenite" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "input_buffer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1564,12 +1586,12 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1620,12 +1642,12 @@ dependencies = [ [[package]] name = "uuid" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1694,7 +1716,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1711,7 +1733,7 @@ name = "xml-rs" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] @@ -1719,25 +1741,25 @@ dependencies = [ "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum arrayref 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0fd1479b7c29641adbd35ff3b5c293922d696a92f25c8c975da3e0acbc87258f" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" -"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" -"checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" +"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" +"checksum backtrace 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea58cd16fd6c9d120b5bcb01d63883ae4cc7ba2aed35c1841b862a3c7ef6639" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" -"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" +"checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum block-buffer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" -"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1d50c876fb7545f5f289cd8b2aee3f359d073ae819eed5d6373638e2c61e59" "checksum cadence 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "99612ce0a00efdaf3d81a5e8e17f0eed55a10e862033183c847a0365983af88c" -"checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" -"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" +"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" -"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" "checksum crossbeam-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1bdc73742c36f7f35ebcda81dbb33a7e0d33757d03a06d9ddca762712ec5ea2" "checksum crossbeam-epoch 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4e2817eb773f770dcb294127c011e22771899c21d18fce7dd739c0b9832e81" @@ -1751,7 +1773,7 @@ dependencies = [ "checksum digest 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "00a49051fef47a72c9623101b19bd71924a45cca838826caae3eaa4d00772603" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d" -"checksum env_logger 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0f475037312b91d34dbc3142a1ad3980ef0d070c7a855ce238afdd5e987cfecc" +"checksum env_logger 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "00c45cec4cde3daac5f036c74098b4956151525cdf360cff5ee0092c98823e54" "checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" @@ -1766,7 +1788,7 @@ dependencies = [ "checksum futures-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5cedfe9b6dc756220782cc1ba5bcb1fa091cdcba155e40d3556159c3db58043" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" -"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e" "checksum hostname 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "58fab6e177434b0bb4cd344a4dabaa5bd6d7a8d792b1885aebcae7af1091d1cb" "checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" @@ -1802,52 +1824,53 @@ dependencies = [ "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" -"checksum openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "63246f69962e8d5ef865f82a65241d6483c8a2905a1801e2f7feb5d187d51320" +"checksum openssl 0.10.7 (registry+https://github.com/rust-lang/crates.io-index)" = "63c6ff2c7d9903daf9f3429eb2f6beedb15b1f7362e3529e5bf00b6caf182400" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" -"checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3" +"checksum openssl-sys 0.9.30 (registry+https://github.com/rust-lang/crates.io-index)" = "73ae718c3562989cd3a0a5c26610feca02f8116822f6f195e6cf4887481e57f5" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8b30dc85588cd02b9b76f5e386535db546d21dc68506cff2abebee0b6445e8e4" -"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" -"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" -"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" -"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" -"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" +"checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" +"checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" +"checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" +"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" -"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" +"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" +"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" -"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rent_to_own 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05a51ad2b1c5c710fa89e6b1631068dab84ed687bc6a5fe061ad65da3d0c25b2" "checksum reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "241faa9a8ca28a03cbbb9815a5d085f271d4c0168a19181f106aa93240c22ddb" "checksum rusoto_core 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12daaa6d62d64f6447bf0299ce775f4e05f8e75e5418e817da094b9de04ad22d" "checksum rusoto_credential 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53199d09fd1b7d4f5ac50f4d23106577624238ea77cae2b44eb1d1fc4cd956a4" "checksum rusoto_dynamodb 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "221fb3362d86a9e6a064cf5f71044cb1cc67a43e7d151008d9ca2a899104c39a" -"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" +"checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4" -"checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" +"checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" +"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" "checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum sentry 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c931969579f133c35280ccc1969a4786984449bd8adad937ef9f76cef3bdfbc" -"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" -"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" -"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" -"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" +"checksum serde 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "6a49d806123bcdaacdefe7aab3721c64ec11d05921bf64d888a857d3a92024a0" +"checksum serde_derive 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "0409f5130e9b06444e07d4c71f55d6a2c4d1290d79faa612d9b0b540a9703fcd" +"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" +"checksum serde_dynamodb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe982f1146e7134af153b2d1fdcab083f09c184600b232cd7a120ec191a4e1b" +"checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1" "checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" "checksum sha1 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "933ed2cffa70bb0e1a2c1bf1174d0f39dd3b81bbf5597d882d886710c8729924" -"checksum sha2 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7daca11f2fdb8559c4f6c588386bed5e2ad4b6605c1442935a7f08144a918688" +"checksum sha2 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" @@ -1860,7 +1883,7 @@ dependencies = [ "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum state_machine_future 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eaafbb574dda413e09727f3a534af6837756c9edb69691c120a3240fa30179da" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum syn 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d5efaad92a0f96c629ae16302cc9591915930fd49ff0dcc6b4cde146782397" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" @@ -1870,17 +1893,18 @@ dependencies = [ "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" -"checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922" +"checksum tokio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d00555353b013e170ed8bc4e13f648a317d1fd12157dbcae13f7013f6cf29f5" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" +"checksum tokio-fs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76766830bbf9a2d5bfb50c95350d56a2e79e2c80f675967fff448bc615899708" "checksum tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af9eb326f64b2d6b68438e1953341e00ab3cf54de7e35d92bfc73af8555313a" "checksum tokio-openssl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e88cd8a247335be936e713ca68a1cb5227df649e22e975b9a71b4e862169e82" "checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-reactor 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3cedc8e5af5131dc3423ffa4f877cce78ad25259a9a62de0613735a13ebc64b" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" "checksum tokio-tcp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec9b094851aadd2caf83ba3ad8e8c4ce65a42104f7b94d9e6550023f0407853f" -"checksum tokio-threadpool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3d05cdd6a78005e535d2b27c21521bdf91fbb321027a62d8e178929d18966d" -"checksum tokio-timer 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29a89e4ad0c8f1e4c9860e605c38c69bfdad3cccd4ea446e58ff588c1c07a397" +"checksum tokio-threadpool 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5783254b10c7c84a56f62c74766ef7e5b83d1f13053218c7cab8d3f2c826fa0e" +"checksum tokio-timer 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535fed0ccee189f3d48447587697ba3fd234b3dbbb091f0ec4613ddfec0a7c4c" "checksum tokio-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "772f4b04e560117fe3b0a53e490c16ddc8ba6ec437015d91fa385564996ed913" "checksum tokio-tungstenite 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3cedf5e2d459171cb08aa6126572a06d827de4208d35281a4cc98081182d5d1a" "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" @@ -1890,8 +1914,8 @@ dependencies = [ "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" +"checksum unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90d662d111b0dbb08a180f2761026cba648c258023c355954a7c00e00e354636" +"checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" @@ -1899,7 +1923,7 @@ dependencies = [ "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc7e3b898aa6f6c08e5295b6c89258d1331e9ac578cc992fb818759951bdc22" -"checksum uuid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4670e1e935f7edd193a413f802e2ee52274aed62a09ccaab1656515c9c53a66" +"checksum uuid 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8630752f979f1b6b87c49830a5e3784082545de63920d59fbaac252474319447" "checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380" "checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/autopush_rs/Cargo.toml b/autopush_rs/Cargo.toml index 1b1ad0a6..a3373dc3 100644 --- a/autopush_rs/Cargo.toml +++ b/autopush_rs/Cargo.toml @@ -17,6 +17,7 @@ futures-backoff = "0.1" hostname = "0.1.4" httparse = "1.2.4" hyper = "0.11.25" +lazy_static = "1.0.0" libc = "0.2.40" # log: Use this version for debug builds # log = "0.4.1" @@ -24,12 +25,14 @@ libc = "0.2.40" log = { version = "0.4.1", features = ["max_level_trace", "release_max_level_warn"] } matches = "0.1.6" openssl = "0.10.5" +regex = "0.2" reqwest = { version = "0.8.5", features = ["unstable"] } rusoto_core = "0.32.0" rusoto_dynamodb = "0.32.0" sentry = "0.2.0" -serde = "1.0.37" -serde_derive = "1.0.37" +serde = "1.0.45" +serde_derive = "1.0.45" +serde_dynamodb = "0.1.2" serde_json = "1.0.13" # slog: Use this first version for debug builds # slog = { version = "2.2.3" , features = ["max_level_trace", "release_max_level_debug"] } diff --git a/autopush_rs/src/call.rs b/autopush_rs/src/call.rs index 9782a0b9..af7760b8 100644 --- a/autopush_rs/src/call.rs +++ b/autopush_rs/src/call.rs @@ -137,13 +137,6 @@ enum Call { code: i32, }, - CheckStorage { - uaid: String, - message_month: String, - include_topic: bool, - timestamp: Option, - }, - DeleteMessage { message: protocol::Notification, message_month: String, @@ -200,13 +193,6 @@ pub enum UnRegisterResponse { }, } -#[derive(Deserialize)] -pub struct CheckStorageResponse { - pub include_topic: bool, - pub messages: Vec, - pub timestamp: Option, -} - #[derive(Deserialize)] pub struct DeleteMessageResponse { pub success: bool, @@ -277,23 +263,6 @@ impl Server { return fut; } - pub fn check_storage( - &self, - uaid: String, - message_month: String, - include_topic: bool, - timestamp: Option, - ) -> MyFuture { - let (call, fut) = PythonCall::new(&Call::CheckStorage { - uaid: uaid, - message_month: message_month, - include_topic: include_topic, - timestamp: timestamp, - }); - self.send_to_python(call); - return fut; - } - pub fn delete_message( &self, message_month: String, diff --git a/autopush_rs/src/client.rs b/autopush_rs/src/client.rs index c7255dee..f8b98b64 100644 --- a/autopush_rs/src/client.rs +++ b/autopush_rs/src/client.rs @@ -15,9 +15,7 @@ use futures::future::Either; use futures::sync::mpsc; use futures::sync::oneshot::Receiver; use futures::{Async, Future, Poll, Sink, Stream}; -use futures_backoff::retry_if; -use rusoto_dynamodb::{AttributeValue, DynamoDb}; -use rusoto_dynamodb::{UpdateItemError, UpdateItemInput, UpdateItemOutput}; +use rusoto_dynamodb::UpdateItemOutput; use state_machine_future::RentToOwn; use tokio_core::reactor::Timeout; use uuid::Uuid; @@ -28,10 +26,9 @@ use errors::*; use protocol::{ClientMessage, Notification, ServerMessage, ServerNotification}; use server::Server; use util::{ms_since_epoch, parse_user_agent, sec_since_epoch}; +use util::ddb_helpers::{CheckStorageResponse}; use util::megaphone::{ClientServices, Service, ServiceClientInit}; -const MAX_EXPIRY: u64 = 2592000; - // Created and handed to the AutopushServer pub struct RegisteredClient { pub uaid: Uuid, @@ -569,7 +566,7 @@ where #[state_machine_future(transitions(SendThenWait, DetermineAck))] AwaitCheckStorage { - response: MyFuture, + response: MyFuture, data: AuthClientData, }, @@ -827,47 +824,13 @@ where .unacked_stored_highest .ok_or("unacked_stored_highest unset")? .to_string(); - let uaid = webpush.uaid.simple().to_string(); - let month_name = webpush.message_month.clone(); - let srv = increment_storage.data.srv.clone(); - let ddb_response = retry_if( - move || { - let expiry = sec_since_epoch() + MAX_EXPIRY; - let mut attr_values = HashMap::new(); - attr_values.insert( - ":timestamp".to_string(), - AttributeValue { - n: Some(timestamp.clone()), - ..Default::default() - }, - ); - attr_values.insert( - ":expiry".to_string(), - AttributeValue { - n: Some(expiry.to_string()), - ..Default::default() - }, - ); - srv.ddb_client.update_item(&UpdateItemInput { - key: ddb_item! { - uaid: s => uaid.clone(), - chidmessageid: s => " ".to_string() - }, - update_expression: Some( - "SET current_timestamp=:timestamp, expiry=:expiry".to_string(), - ), - expression_attribute_values: Some(attr_values), - table_name: month_name.clone(), - ..Default::default() - }) - }, - |err: &UpdateItemError| { - matches!(err, &UpdateItemError::ProvisionedThroughputExceeded(_)) - }, - ).map_err(|_| "Error incrementing storage".into()); - + let ddb_response = increment_storage.data.srv.ddb.increment_storage( + &webpush.message_month, + &webpush.uaid, + ×tamp + ); transition!(AwaitIncrementStorage { - ddb_response: Box::new(ddb_response), + ddb_response, data: increment_storage.take().data, }) } @@ -890,9 +853,9 @@ where let CheckStorage { data } = check_storage.take(); let response = { let webpush = data.webpush.borrow(); - data.srv.check_storage( - webpush.uaid.simple().to_string(), - webpush.message_month.clone(), + data.srv.ddb.check_storage( + &webpush.message_month.clone(), + &webpush.uaid, webpush.flags.include_topic, webpush.unacked_stored_highest, ) @@ -906,7 +869,7 @@ where debug!("State: AwaitCheckStorage"); let (include_topic, mut messages, timestamp) = match try_ready!(await_check_storage.response.poll()) { - call::CheckStorageResponse { + CheckStorageResponse { include_topic, messages, timestamp, diff --git a/autopush_rs/src/errors.rs b/autopush_rs/src/errors.rs index b6048807..9ee0b9af 100644 --- a/autopush_rs/src/errors.rs +++ b/autopush_rs/src/errors.rs @@ -24,6 +24,7 @@ //! online. use std::any::Any; +use std::num; use std::error; use std::io; @@ -33,6 +34,7 @@ use httparse; use serde_json; use sentry; use tungstenite; +use uuid; error_chain! { foreign_links { @@ -42,6 +44,8 @@ error_chain! { Httparse(httparse::Error); MetricError(cadence::MetricError); SentryError(sentry::Error); + UuidParseError(uuid::ParseError); + ParseIntError(num::ParseIntError); } errors { diff --git a/autopush_rs/src/lib.rs b/autopush_rs/src/lib.rs index 213f2d6c..a46fd7de 100644 --- a/autopush_rs/src/lib.rs +++ b/autopush_rs/src/lib.rs @@ -69,10 +69,13 @@ extern crate futures_backoff; extern crate hostname; extern crate httparse; extern crate hyper; +#[macro_use] +extern crate lazy_static; extern crate libc; #[macro_use] extern crate matches; extern crate openssl; +extern crate regex; extern crate reqwest; extern crate rusoto_core; extern crate rusoto_dynamodb; @@ -80,6 +83,7 @@ extern crate sentry; extern crate serde; #[macro_use] extern crate serde_derive; +extern crate serde_dynamodb; #[macro_use] extern crate slog; #[macro_use] diff --git a/autopush_rs/src/protocol.rs b/autopush_rs/src/protocol.rs index eab365f3..95074d51 100644 --- a/autopush_rs/src/protocol.rs +++ b/autopush_rs/src/protocol.rs @@ -116,7 +116,7 @@ pub struct Notification { #[serde(skip_serializing)] pub sortkey_timestamp: Option, #[serde(skip_serializing_if = "Option::is_none")] - headers: Option>, + pub headers: Option>, } diff --git a/autopush_rs/src/server/mod.rs b/autopush_rs/src/server/mod.rs index 57be007f..95776502 100644 --- a/autopush_rs/src/server/mod.rs +++ b/autopush_rs/src/server/mod.rs @@ -22,8 +22,6 @@ use hyper::{self, header, StatusCode}; use libc::c_char; use openssl::ssl::SslAcceptor; use reqwest; -use rusoto_core::{Region}; -use rusoto_dynamodb::{DynamoDbClient}; use sentry; use serde_json; use time; @@ -46,6 +44,7 @@ use server::dispatch::{Dispatch, RequestType}; use server::metrics::metrics_from_opts; use server::webpush_io::WebpushIo; use util::{self, RcObject, timeout}; +use util::ddb_helpers::DynamoStorage; use util::megaphone::{ClientServices, MegaphoneAPIResponse, Service, ServiceClientInit, ServiceChangeTracker}; mod dispatch; @@ -93,7 +92,7 @@ pub struct AutopushServerOptions { pub struct Server { uaids: RefCell>, broadcaster: RefCell, - pub ddb_client: DynamoDbClient, + pub ddb: DynamoStorage, open_connections: Cell, tls_acceptor: Option, pub tx: queue::Sender, @@ -339,17 +338,10 @@ impl Server { } else { ServiceChangeTracker::new(Vec::new()) }; - let region = env::var("AWS_LOCAL_DYNAMODB").map(|endpoint| { - Region::Custom { - endpoint, - name: "env_var".to_string(), - } - }).unwrap_or(Region::default()); - let ddb_client = DynamoDbClient::simple(region); let srv = Rc::new(Server { opts: opts.clone(), broadcaster: RefCell::new(broadcaster), - ddb_client: ddb_client, + ddb: DynamoStorage::new(), uaids: RefCell::new(HashMap::new()), open_connections: Cell::new(0), handle: core.handle(), diff --git a/autopush_rs/src/util/ddb_helpers.rs b/autopush_rs/src/util/ddb_helpers.rs index 220c7642..8c665890 100644 --- a/autopush_rs/src/util/ddb_helpers.rs +++ b/autopush_rs/src/util/ddb_helpers.rs @@ -1,3 +1,24 @@ +/// DynamoDB Client helpers +use std::env; +use std::collections::{HashMap, HashSet}; +use std::rc::Rc; +use uuid::Uuid; + +use futures::Future; +use futures::future; +use futures_backoff::retry_if; +use regex::RegexSet; +use rusoto_core::Region; +use rusoto_dynamodb::{AttributeValue, DynamoDb, DynamoDbClient, QueryError, QueryInput, + UpdateItemError, UpdateItemInput, UpdateItemOutput}; +use serde_dynamodb; +use time; + +use protocol::Notification; +use errors::*; + +const MAX_EXPIRY: u64 = 2592000; + /// A bunch of macro helpers from rusoto_helpers code, which they pulled from crates.io because /// they were waiting for rusuto to hit 1.0.0 or something. For sanity, they are instead accumulated /// here for our use. @@ -7,7 +28,10 @@ macro_rules! attributes { { let mut temp_vec = Vec::new(); $( - temp_vec.push(AttributeDefinition { attribute_name: String::from($val), attribute_type: String::from($attr_type) }); + temp_vec.push(AttributeDefinition { + attribute_name: String::from($val), + attribute_type: String::from($attr_type) + }); )* temp_vec } @@ -20,7 +44,10 @@ macro_rules! key_schema { { let mut temp_vec = Vec::new(); $( - temp_vec.push(KeySchemaElement { key_type: String::from($key_type), attribute_name: String::from($name) }); + temp_vec.push(KeySchemaElement { + key_type: String::from($key_type), + attribute_name: String::from($name) + }); )* temp_vec } @@ -102,3 +129,479 @@ macro_rules! ddb_item { } } } + +/// Direct representation of a DynamoDB Notification as we store it in the database +/// Most attributes are optional +#[derive(Default, Deserialize, PartialEq, Debug, Clone)] +pub struct NotificationHeaders { + crypto_key: Option, + encryption: Option, + encryption_key: Option, + encoding: Option, +} + +fn insert_to_map(map: &mut HashMap, val: Option, name: &str) { + if let Some(val) = val { + map.insert(name.to_string(), val); + } +} + +impl From for HashMap { + fn from(val: NotificationHeaders) -> HashMap { + let mut map = HashMap::new(); + insert_to_map(&mut map, val.crypto_key, "crypto_key"); + insert_to_map(&mut map, val.encryption, "encryption"); + insert_to_map(&mut map, val.encryption_key, "encryption_key"); + insert_to_map(&mut map, val.encoding, "encoding"); + map + } +} + +#[derive(Default, Deserialize, PartialEq, Debug, Clone)] +pub struct DynamoDbNotification { + // DynamoDB + uaid: Uuid, + // DynamoDB + // Format: + // Topic Messages: + // 01:{channel id}:{topic} + // New Messages: + // 02:{timestamp int in microseconds}:{channel id} + chidmessageid: String, + // Magic entry stored in the first Message record that indicates the highest + // non-topic timestamp we've read into + current_timestamp: Option, + // Magic entry stored in the first Message record that indicates the valid + // channel id's + chids: Option>, + // Time in seconds from epoch + timestamp: Option, + // DynamoDB expiration timestamp per + // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html + expiry: u32, + // TTL value provided by application server for the message + ttl: Option, + data: Option, + headers: Option, + // This is the acknowledgement-id used for clients to ack that they have received the + // message. Some Python code refers to this as a message_id. Endpoints generate this + // value before sending it to storage or a connection node. + updateid: Option, +} + +struct RangeKey { + channel_id: Uuid, + topic: Option, + sortkey_timestamp: Option, + legacy_version: Option, +} + +fn parse_sort_key(key: &str) -> Result { + lazy_static! { + static ref RE: RegexSet = RegexSet::new(&[ + r"^01:\S+:\S+$", + r"^02:\d+:\S+$", + r"^\S{3,}:\S+$", + ]).unwrap(); + } + if !RE.is_match(key) { + return Err("Invalid chidmessageid".into()).into(); + } + if key.starts_with("01:") { + let v: Vec<&str> = key.split(":").collect(); + if v.len() != 3 { + return Err("Invalid topic key".into()); + } + let (channel_id, topic) = (v[1], v[2]); + let channel_id = Uuid::parse_str(channel_id)?; + Ok(RangeKey { + channel_id, + topic: Some(topic.to_string()), + sortkey_timestamp: None, + legacy_version: None, + }) + } else if key.starts_with("02:") { + let v: Vec<&str> = key.split(":").collect(); + if v.len() != 3 { + return Err("Invalid topic key".into()); + } + let (sortkey, channel_id) = (v[1], v[2]); + let channel_id = Uuid::parse_str(channel_id)?; + Ok(RangeKey { + channel_id, + topic: None, + sortkey_timestamp: Some(sortkey.parse()?), + legacy_version: None, + }) + } else { + let v: Vec<&str> = key.split(":").collect(); + if v.len() != 2 { + return Err("Invalid topic key".into()); + } + let (channel_id, legacy_version) = (v[0], v[1]); + let channel_id = Uuid::parse_str(channel_id)?; + Ok(RangeKey { + channel_id, + topic: None, + sortkey_timestamp: None, + legacy_version: Some(legacy_version.to_string()), + }) + } +} + +impl DynamoDbNotification { + fn to_notif(self) -> Result { + let key = parse_sort_key(&self.chidmessageid)?; + let version = key.legacy_version + .or(self.updateid) + .ok_or("No valid updateid/version found")?; + + Ok(Notification { + uaid: Some(self.uaid.simple().to_string()), + channel_id: key.channel_id, + version, + ttl: self.ttl.ok_or("No TTL found")?, + timestamp: self.timestamp.ok_or("No timestamp found")?, + topic: key.topic, + data: self.data, + headers: self.headers.map(|m| m.into()), + sortkey_timestamp: key.sortkey_timestamp, + }) + } +} + +/// + +/// Basic requirements for notification content to deliver to websocket client +// - channelID (the subscription website intended for) +// - version (only really utilized for notification acknowledgement in +// webpush, used to be the sole carrier of data, can now be anything) +// - data (encrypted content) +// - headers (hash of crypto headers: encoding, encrypption, crypto-key, encryption-key) + +pub struct CheckStorageResponse { + pub include_topic: bool, + pub messages: Vec, + pub timestamp: Option, +} + +#[derive(Default)] +pub struct FetchMessageResponse { + pub timestamp: Option, + pub messages: Option>, +} + +pub struct DynamoStorage { + ddb: Rc, +} + +impl DynamoStorage { + pub fn new() -> DynamoStorage { + let region = env::var("AWS_LOCAL_DYNAMODB") + .map(|endpoint| Region::Custom { + endpoint, + name: "env_var".to_string(), + }) + .unwrap_or(Region::default()); + DynamoStorage { + ddb: Rc::new(DynamoDbClient::simple(region)), + } + } + + pub fn increment_storage( + &self, + table_name: &str, + uaid: &Uuid, + timestamp: &str, + ) -> MyFuture { + let ddb = self.ddb.clone(); + let uaid = uaid.simple().to_string(); + let table_name = table_name.to_string(); + let timestamp = timestamp.to_string(); + let ddb_response = retry_if( + move || { + let expiry = (time::get_time().sec as u64) + MAX_EXPIRY; + let mut attr_values = HashMap::new(); + attr_values.insert( + ":timestamp".to_string(), + AttributeValue { + n: Some(timestamp.clone()), + ..Default::default() + }, + ); + attr_values.insert( + ":expiry".to_string(), + AttributeValue { + n: Some(expiry.to_string()), + ..Default::default() + }, + ); + ddb.update_item(&UpdateItemInput { + key: ddb_item! { + uaid: s => uaid.clone(), + chidmessageid: s => " ".to_string() + }, + update_expression: Some( + "SET current_timestamp=:timestamp, expiry=:expiry".to_string(), + ), + expression_attribute_values: Some(attr_values), + table_name: table_name.clone(), + ..Default::default() + }) + }, + |err: &UpdateItemError| { + matches!(err, &UpdateItemError::ProvisionedThroughputExceeded(_)) + }, + ).map_err(|_| "Error incrementing storage".into()); + Box::new(ddb_response) + } + + pub fn fetch_messages( + ddb: Rc, + table_name: &str, + uaid: &Uuid, + limit: u32, + ) -> MyFuture { + let uaid = uaid.simple().to_string(); + let table_name = table_name.to_string(); + let response = retry_if( + move || { + let mut attr_values = HashMap::new(); + attr_values.insert( + ":uaid".to_string(), + AttributeValue { + s: Some(uaid.clone()), + ..Default::default() + }, + ); + attr_values.insert( + ":cmi".to_string(), + AttributeValue { + s: Some("02".to_string()), + ..Default::default() + }, + ); + ddb.query(&QueryInput { + key_condition_expression: Some( + "uaid = :uaid AND chidmessageid < :cmi".to_string(), + ), + expression_attribute_values: Some(attr_values), + table_name: table_name.clone(), + limit: Some(limit as i64), + ..Default::default() + }) + }, + |err: &QueryError| matches!(err, &QueryError::ProvisionedThroughputExceeded(_)), + ).map_err(|_| "Error fetching messages".into()); + let response = response.and_then(|data| { + let mut notifs: Option> = data.items.and_then(|items| { + debug!("Got response of: {:?}", items); + // TODO: Capture translation errors and report them as we shouldn't have corrupt data + Some( + items + .into_iter() + .inspect(|i| debug!("Item: {:?}", i)) + .filter_map(|item| serde_dynamodb::from_hashmap(item).ok()) + .collect(), + ) + }); + // Load the current_timestamp from the subscription registry entry which is + // the first DynamoDbNotification and remove it from the vec. + let mut timestamp = None; + if let Some(ref mut messages) = notifs { + if messages.len() == 0 { + return Ok(Default::default()); + } + let first = messages.remove(0); + if let Some(ts) = first.current_timestamp { + timestamp = Some(ts); + } + } + // Convert any remaining DynamoDbNotifications to Notification's + let notifs = notifs.and_then(|items| { + // TODO: Capture translation errors and report them as we shouldn't have corrupt data + let items: Vec = items + .into_iter() + .filter_map(|ddb_notif| ddb_notif.to_notif().ok()) + .collect(); + if items.len() > 0 { + Some(items) + } else { + None + } + }); + Ok(FetchMessageResponse { + timestamp, + messages: notifs, + }) + }); + Box::new(response) + } + + pub fn fetch_timestamp_messages( + ddb: Rc, + table_name: &str, + uaid: &Uuid, + timestamp: Option, + limit: u32, + ) -> MyFuture { + let uaid = uaid.simple().to_string(); + let table_name = table_name.to_string(); + let timestamp = timestamp.clone(); + let response = retry_if( + move || { + let mut attr_values = HashMap::new(); + attr_values.insert( + ":uaid".to_string(), + AttributeValue { + s: Some(uaid.clone()), + ..Default::default() + }, + ); + let range_key = if let Some(ts) = timestamp { + format!("02:{}:z", ts) + } else { + "01;".to_string() + }; + attr_values.insert( + ":cmi".to_string(), + AttributeValue { + s: Some(range_key), + ..Default::default() + }, + ); + ddb.query(&QueryInput { + key_condition_expression: Some( + "uaid = :uaid AND chidmessageid > :cmi".to_string(), + ), + expression_attribute_values: Some(attr_values), + table_name: table_name.clone(), + limit: Some(limit as i64), + ..Default::default() + }) + }, + |err: &QueryError| matches!(err, &QueryError::ProvisionedThroughputExceeded(_)), + ).map_err(|_| "Error fetching messages".into()); + let response = response.and_then(|data| { + let notifs: Option> = data.items.and_then(|items| { + debug!("Got response of: {:?}", items); + // TODO: Capture translation errors and report them as we shouldn't have corrupt data + Some( + items + .into_iter() + .filter_map(|item| serde_dynamodb::from_hashmap(item).ok()) + .filter_map(|ddb_notif: DynamoDbNotification| ddb_notif.to_notif().ok()) + .collect(), + ) + }); + let mut timestamp = None; + if let Some(ref messages) = notifs { + if messages.len() == 0 { + return Ok(Default::default()); + } + timestamp = messages.iter().filter_map(|m| m.sortkey_timestamp).max(); + } + Ok(FetchMessageResponse { + timestamp, + messages: notifs, + }) + }); + Box::new(response) + } + + pub fn check_storage( + &self, + table_name: &str, + uaid: &Uuid, + include_topic: bool, + timestamp: Option, + ) -> MyFuture { + let ddb = self.ddb.clone(); + let response: MyFuture = if include_topic { + DynamoStorage::fetch_messages(ddb, table_name, uaid, 11 as u32) + } else { + Box::new(future::ok(Default::default())) + }; + let uaid = uaid.clone(); + let table_name = table_name.to_string(); + let ddb2 = self.ddb.clone(); + let response = response.and_then(move |resp| { + // Return now from this future if we have messages + if let Some(messages) = resp.messages { + debug!("Topic message returns: {:?}", messages); + return future::Either::A(future::ok(CheckStorageResponse { + include_topic: true, + messages, + timestamp: resp.timestamp, + })); + } + // Use the timestamp returned by the topic query if we were looking at the topics + let timestamp = if include_topic { + resp.timestamp + } else { + timestamp + }; + let next_query = { + if resp.messages.is_none() || resp.timestamp.is_some() { + DynamoStorage::fetch_timestamp_messages( + ddb2, + table_name.as_ref(), + &uaid, + timestamp, + 10 as u32, + ) + } else { + Box::new(future::ok(Default::default())) + } + }; + let next_query = next_query.and_then(move |resp: FetchMessageResponse| { + // If we didn't get a timestamp off the last query, use the original + // value if passed one + let timestamp = resp.timestamp.or(timestamp); + Ok(CheckStorageResponse { + include_topic: false, + messages: resp.messages.unwrap_or(Vec::new()), + timestamp, + }) + }); + future::Either::B(next_query) + }); + Box::new(response) + } +} + +#[cfg(test)] +mod tests { + use uuid::Uuid; + use util::us_since_epoch; + use super::parse_sort_key; + + #[test] + fn test_parse_sort_key_ver1() { + let chid = Uuid::new_v4(); + let chidmessageid = format!("01:{}:mytopic", chid.hyphenated().to_string()); + let key = parse_sort_key(&chidmessageid).unwrap(); + assert_eq!(key.topic, Some("mytopic".to_string())); + assert_eq!(key.channel_id, chid); + assert_eq!(key.sortkey_timestamp, None); + } + + #[test] + fn test_parse_sort_key_ver2() { + let chid = Uuid::new_v4(); + let sortkey_timestamp = us_since_epoch(); + let chidmessageid = format!("02:{}:{}", sortkey_timestamp, chid.hyphenated().to_string()); + let key = parse_sort_key(&chidmessageid).unwrap(); + assert_eq!(key.topic, None); + assert_eq!(key.channel_id, chid); + assert_eq!(key.sortkey_timestamp, Some(sortkey_timestamp)); + } + + #[test] + fn test_parse_sort_key_bad_values() { + for val in vec!["02j3i2o", "03:ffas:wef", "01::mytopic", "02:oops:ohnoes"] { + let key = parse_sort_key(val); + assert!(key.is_err()); + } + } +}