Skip to content

Commit 03a580e

Browse files
committed
Implement auto retries under a config feature flag
Signed-off-by: Mateusz Szczygieł <[email protected]>
1 parent 4576bd6 commit 03a580e

File tree

9 files changed

+203
-35
lines changed

9 files changed

+203
-35
lines changed

Cargo.lock

Lines changed: 29 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Update moose tracker to v13.1.0
66
* Adds the `transfer_intent_received` event
77
* Added private key retrieval on demand instead of caching it
8+
* Add internal retries and put under a config feature `auto_retry_interval_ms`
89

910
---
1011
<br>

drop-config/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub struct DropConfig {
1717
// Default value is 256KB.
1818
pub checksum_events_granularity: u64,
1919
pub connection_retries: u32,
20+
pub auto_retry_interval: Option<Duration>,
2021
}
2122

2223
impl Default for DropConfig {
@@ -28,6 +29,7 @@ impl Default for DropConfig {
2829
checksum_events_size_threshold: None,
2930
checksum_events_granularity: 256 * 1024,
3031
connection_retries: 5,
32+
auto_retry_interval: None,
3133
}
3234
}
3335
}

drop-transfer/src/service.rs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use std::{
33
net::IpAddr,
44
path::{Component, Path},
55
sync::Arc,
6-
time::{Instant, SystemTime},
6+
time::{Duration, Instant, SystemTime},
77
};
88

99
use drop_analytics::{InitEventData, Moose, TransferStateEventData};
1010
use drop_config::DropConfig;
1111
use drop_core::Status;
1212
use drop_storage::Storage;
13-
use slog::{debug, trace, Logger};
13+
use slog::{debug, info, trace, Logger};
1414
use tokio::sync::{mpsc, Semaphore};
1515
use tokio_util::sync::CancellationToken;
1616
use uuid::Uuid;
@@ -19,7 +19,7 @@ use crate::{
1919
auth,
2020
error::ResultExt,
2121
manager::{self},
22-
tasks::AliveWaiter,
22+
tasks::{AliveGuard, AliveWaiter},
2323
transfer::Transfer,
2424
ws::{self, EventTxFactory},
2525
Error, Event, FileId, TransferManager,
@@ -106,12 +106,22 @@ impl Service {
106106

107107
manager::resume(&refresh_trigger.subscribe(), &state, &logger, &guard, &stop).await;
108108

109+
if let Some(interval) = state.config.auto_retry_interval {
110+
spawn_auto_retry_loop(
111+
refresh_trigger.clone(),
112+
interval,
113+
logger.clone(),
114+
guard.clone(),
115+
stop.clone(),
116+
);
117+
}
118+
109119
Ok(Self {
110120
refresh_trigger,
111121
state,
112122
stop,
113123
waiter,
114-
logger: logger.clone(),
124+
logger,
115125
})
116126
};
117127

@@ -335,3 +345,37 @@ fn validate_dest_path(parent_dir: &Path) -> crate::Result<()> {
335345

336346
Ok(())
337347
}
348+
349+
fn spawn_auto_retry_loop(
350+
trigger: tokio::sync::watch::Sender<()>,
351+
interval: Duration,
352+
logger: Logger,
353+
guard: AliveGuard,
354+
stop: CancellationToken,
355+
) {
356+
info!(
357+
logger,
358+
"Starting auto retry loop with interval: {}ms",
359+
interval.as_millis()
360+
);
361+
362+
tokio::spawn(async move {
363+
let _guard = guard;
364+
365+
let task = async {
366+
loop {
367+
tokio::time::sleep(interval).await;
368+
let _ = trigger.send(());
369+
}
370+
};
371+
372+
tokio::select! {
373+
biased;
374+
375+
_ = stop.cancelled() => {
376+
debug!(logger, "Stopping auto retry loop");
377+
},
378+
_ = task => (),
379+
}
380+
});
381+
}

norddrop/src/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::Duration;
2+
13
#[derive(Debug)]
24
pub struct Config {
35
pub dir_depth_limit: u64,
@@ -8,6 +10,7 @@ pub struct Config {
810
pub checksum_events_size_threshold: Option<u64>,
911
pub checksum_events_granularity: Option<u64>,
1012
pub connection_retries: Option<u32>,
13+
pub auto_retry_interval_ms: Option<u32>,
1114
}
1215

1316
impl Config {
@@ -31,6 +34,7 @@ impl From<Config> for drop_config::Config {
3134
checksum_events_size_threshold,
3235
checksum_events_granularity,
3336
connection_retries,
37+
auto_retry_interval_ms,
3438
} = val;
3539

3640
drop_config::Config {
@@ -43,6 +47,8 @@ impl From<Config> for drop_config::Config {
4347
.unwrap_or(Config::default_checksum_granularity() as _),
4448
connection_retries: connection_retries
4549
.unwrap_or(Config::default_connection_retries()),
50+
auto_retry_interval: auto_retry_interval_ms
51+
.map(|ms| Duration::from_millis(ms as _)),
4652
},
4753
moose: drop_config::MooseConfig {
4854
event_path: moose_event_path,

norddrop/src/norddrop.udl

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,29 @@ dictionary Config {
5858
/// Emit checksum events at set granularity
5959
u64? checksum_events_granularity;
6060

61-
/// Limits the number of connection retries afer the `network_refresh()` call.
61+
/// Limits the number of burst connection retries after the
62+
/// `network_refresh()` call. Setting this to `0` or `1` gives an effect of
63+
/// only one retry after `network_refresh()` call.
64+
/// When set to `n > 1` the retry happens in a burst of `n` times and the
65+
/// interval between burst retries is increased by the power of 2 starting
66+
/// from 1-second interval. For example for `n = 5` the retries happen
67+
/// * 1st burst retry immediately
68+
/// * 2nd burst retry after 1s the previous burst retry
69+
/// * 3rd burst retry after 2s the previous burst retry
70+
/// * 4th burst retry after 4s the previous burst retry
71+
/// * 5th burst retry after 8s the previous burst retry
72+
/// When set to `null` the default of 5 burst retries is used.
6273
u32? connection_retries;
74+
75+
/// Enable auto retry loop inside libdrop. Conceptually this means that
76+
/// libdrop is calling `network_refresh()` automatically with the given
77+
/// period in milliseconds. When set to `null` the feature is disabled and
78+
/// the application needs to call `network_refresh()` manually.
79+
/// Note the setting `connection_retries` still applies, meaning the retry
80+
/// is executed in burst with this number of counts.
81+
/// For example for a single retry every 5 seconds the application needs to
82+
/// set `connection_retries` to `1` or `0` and `auto_retry_interval_ms = 5000`.
83+
u32? auto_retry_interval_ms;
6384
};
6485

6586
/// Posible log levels.

test/drop_test/action.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,18 +974,21 @@ def __init__(
974974
dbpath: str = ":memory:",
975975
checksum_events_size_threshold=2**32, # don't emit events for existing tests
976976
checksum_events_granularity=None,
977+
auto_retry_interval_ms=None,
977978
):
978979
self._addr = addr
979980
self._dbpath = dbpath
980981
self._checksum_events_size_threshold = checksum_events_size_threshold
981982
self._checksum_events_granularity = checksum_events_granularity
983+
self._auto_retry_interval_ms = auto_retry_interval_ms
982984

983985
async def run(self, drop: ffi.Drop):
984986
drop.start(
985987
peer_resolver.resolve(self._addr),
986988
self._dbpath,
987989
self._checksum_events_size_threshold,
988990
self._checksum_events_granularity,
991+
self._auto_retry_interval_ms,
989992
)
990993

991994
def __str__(self):

test/drop_test/ffi.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ def start(
322322
dbpath: str,
323323
checksum_events_size_threshold=None,
324324
checksum_events_granularity=None,
325+
auto_retry_interval_ms=None,
325326
):
326327
cfg = norddrop.Config(
327328
dir_depth_limit=5,
@@ -332,6 +333,7 @@ def start(
332333
checksum_events_size_threshold=checksum_events_size_threshold,
333334
checksum_events_granularity=checksum_events_granularity,
334335
connection_retries=1,
336+
auto_retry_interval_ms=auto_retry_interval_ms,
335337
)
336338

337339
self._instance.start(addr, cfg)

0 commit comments

Comments
 (0)