Skip to content

Commit ddea501

Browse files
authored
Merge pull request #181 from dfint/retry-fetch
2 parents 19bf923 + 31e464d commit ddea501

File tree

8 files changed

+106
-30
lines changed

8 files changed

+106
-30
lines changed

Cargo.lock

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

src/constants.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ pub const ORIGINAL_FONT: &'static [u8; 1568] = include_bytes!("../assets/origina
1212
pub const PATH_CACHE_FILE: &'static str = "./dfint-installer.cache";
1313
pub const PATH_ERROR_FILE: &'static str = "./dfint-error.log";
1414

15-
pub const URL_HOOK_MANIFEST: &'static str = "https://dfint.github.io/update-data/metadata/hook_v2.json";
16-
pub const URL_DICT_MANIFEST: &'static str = "https://dfint.github.io/update-data/metadata/dict.json";
15+
pub const BASE_URL: [&'static str; 2] = [
16+
"https://dfint.github.io",
17+
"https://gitverse.ru/api/repos/dfint/data-mirror/raw/branch/master",
18+
];
19+
20+
pub const URL_HOOK_MANIFEST: &'static str = "/update-data/metadata/hook_v3.json";
21+
pub const URL_DICT_MANIFEST: &'static str = "/update-data/metadata/dict_v3.json";
1722
pub const URL_BUGS: &'static str = "https://github.com/dfint/installer/issues";
1823
pub const URL_TRANSIFEX: &'static str =
1924
"https://explore.transifex.com/dwarf-fortress-translation/dwarf-fortress-steam/";

src/dict_metadata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use anyhow::Result;
22

3+
use crate::fetch;
4+
35
#[derive(Debug, Serialize, Deserialize, Clone)]
46
pub struct Manifest {
57
pub language: String,
@@ -31,7 +33,7 @@ pub struct DictMetadata {
3133

3234
impl DictMetadata {
3335
pub async fn from_url(url: &str, pick_language: Option<String>) -> Result<Self> {
34-
let manifests: Vec<Manifest> = ureq::get(url).call()?.into_json()?;
36+
let manifests: Vec<Manifest> = fetch::fetch_json(url)?;
3537

3638
let picked = match pick_language {
3739
Some(language) => {

src/fetch.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use anyhow::Result;
2+
use std::{
3+
path::PathBuf,
4+
sync::atomic::{AtomicUsize, Ordering},
5+
};
6+
7+
use crate::{constants::BASE_URL, fetch};
8+
9+
static BASE_URL_INDEX: AtomicUsize = AtomicUsize::new(0);
10+
11+
pub fn get_base_url() -> &'static str {
12+
let index = BASE_URL_INDEX.load(Ordering::Relaxed);
13+
BASE_URL[index.min(BASE_URL.len() - 1)]
14+
}
15+
16+
pub fn switch_to_next_base_url() {
17+
BASE_URL_INDEX
18+
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |index| {
19+
let max_index = BASE_URL.len() - 1;
20+
if index < max_index { Some(index + 1) } else { None }
21+
})
22+
.ok();
23+
}
24+
25+
pub fn fetch_json<T: for<'de> serde::Deserialize<'de>>(path: &str) -> Result<T> {
26+
let base_url = get_base_url();
27+
let url = format!("{}{}", base_url, path);
28+
29+
match ureq::get(&url).call() {
30+
Ok(res) => Ok(res.into_json().unwrap()),
31+
Err(e) => {
32+
if get_base_url() == base_url {
33+
switch_to_next_base_url();
34+
if get_base_url() != base_url {
35+
return fetch_json(path);
36+
}
37+
} else {
38+
return fetch_json(path);
39+
}
40+
41+
Err(anyhow::Error::from(e))
42+
}
43+
}
44+
}
45+
46+
pub fn fetch_bytes(path: &str) -> Result<Vec<u8>> {
47+
let base_url = get_base_url();
48+
let url = format!("{}{}", base_url, path);
49+
50+
match ureq::get(&url).call() {
51+
Ok(res) => {
52+
let mut bytes = Vec::new();
53+
res.into_reader().read_to_end(&mut bytes)?;
54+
Ok(bytes)
55+
}
56+
Err(e) => {
57+
if get_base_url() == base_url {
58+
switch_to_next_base_url();
59+
if get_base_url() != base_url {
60+
return fetch_bytes(path);
61+
}
62+
} else {
63+
return fetch_bytes(path);
64+
}
65+
66+
Err(anyhow::Error::from(e))
67+
}
68+
}
69+
}
70+
71+
pub async fn download_to_file(url: String, file: PathBuf) -> Result<()> {
72+
let data: Vec<u8> = fetch::fetch_bytes(&url)?;
73+
std::fs::write(file, &data)?;
74+
Ok(())
75+
}
76+
77+
pub async fn batch_download_to_file(items: Vec<(String, PathBuf)>) -> Result<()> {
78+
let result = futures::future::join_all(
79+
items
80+
.iter()
81+
.map(|item| download_to_file(item.0.clone(), item.1.clone())),
82+
)
83+
.await;
84+
for item in result {
85+
item?;
86+
}
87+
Ok(())
88+
}

src/hook_metadata.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use anyhow::Result;
22

3+
use crate::fetch;
4+
35
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
46
pub struct Manifest {
57
pub df: u32,
@@ -18,7 +20,7 @@ pub struct HookMetadata {
1820

1921
impl HookMetadata {
2022
pub async fn from_url(url: &str, pick_df_checksum: Option<u32>) -> Result<Self> {
21-
let manifests: Vec<Manifest> = ureq::get(url).call()?.into_json()?;
23+
let manifests: Vec<Manifest> = fetch::fetch_json(url)?;
2224

2325
let picked = match pick_df_checksum {
2426
Some(checksum) => {

src/logic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
constants::*,
99
df_binary::DfBinary,
1010
dict_metadata::DictMetadata,
11+
fetch::batch_download_to_file,
1112
hook_metadata::HookMetadata,
1213
localization::{LOCALE, t},
1314
persistent::Store,

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod app;
1212
mod constants;
1313
mod df_binary;
1414
mod dict_metadata;
15+
mod fetch;
1516
mod hook_metadata;
1617
mod localization;
1718
mod logic;

src/utils.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,3 @@ pub async fn is_df_running() -> bool {
3535
.contains(&val.name())
3636
})
3737
}
38-
39-
pub async fn download_to_file(url: String, file: PathBuf) -> Result<()> {
40-
let mut data: Vec<u8> = vec![];
41-
ureq::get(&url)
42-
.call()?
43-
.into_reader()
44-
.read_to_end(&mut data)?;
45-
std::fs::write(file, &data)?;
46-
Ok(())
47-
}
48-
49-
pub async fn batch_download_to_file(items: Vec<(String, PathBuf)>) -> Result<()> {
50-
let result = futures::future::join_all(
51-
items
52-
.iter()
53-
.map(|item| download_to_file(item.0.clone(), item.1.clone())),
54-
)
55-
.await;
56-
for item in result {
57-
item?;
58-
}
59-
Ok(())
60-
}

0 commit comments

Comments
 (0)