Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
Paul van Tilburg | c070877384 | |
Paul van Tilburg | 732d4b83f2 | |
Paul van Tilburg | 12a797baa9 | |
Paul van Tilburg | 5586ae4d70 | |
Paul van Tilburg | 59e3b53263 | |
Paul van Tilburg | f236499125 | |
Paul van Tilburg | 02a4d1ca9b | |
Paul van Tilburg | 3fff79a2cd | |
Paul van Tilburg | 9200a10cef |
|
@ -5,9 +5,6 @@ target
|
|||
Dockerfile*
|
||||
docker-compose*
|
||||
|
||||
# Git folder
|
||||
.git
|
||||
|
||||
# Dot files
|
||||
.gitignore
|
||||
|
||||
|
|
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.3.0] - 2023-04-15
|
||||
|
||||
### Added
|
||||
|
||||
* Implement backoff for login/update API call failures (#8)
|
||||
|
||||
### Changed
|
||||
|
||||
* Update dependencies
|
||||
* Speed up Docker image builds by using sparse Cargo index for crates.io
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fix login errors not being detected for My Autarco
|
||||
* Fix missing build script/git repository during Docker image build
|
||||
|
||||
## [0.2.2] - 2023-03-22
|
||||
|
||||
### Added
|
||||
|
@ -65,7 +81,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
Rename Autarco Scraper project to Solar Grabber.
|
||||
|
||||
[Unreleased]: https://git.luon.net/paul/solar-grabber/compare/v0.2.2...HEAD
|
||||
[Unreleased]: https://git.luon.net/paul/solar-grabber/compare/v0.3.0...HEAD
|
||||
[0.3.0]: https://git.luon.net/paul/solar-grabber/compare/v0.2.2...v0.3.0
|
||||
[0.2.2]: https://git.luon.net/paul/solar-grabber/compare/v0.2.1...v0.2.2
|
||||
[0.2.1]: https://git.luon.net/paul/solar-grabber/compare/v0.2.0...v0.2.1
|
||||
[0.2.0]: https://git.luon.net/paul/solar-grabber/compare/v0.1.1...v0.2.0
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "solar-grabber"
|
||||
version = "0.2.2"
|
||||
version = "0.3.0"
|
||||
authors = ["Paul van Tilburg <paul@luon.net>"]
|
||||
edition = "2021"
|
||||
description = """"
|
||||
|
@ -19,13 +19,12 @@ enum_dispatch = "0.3.9"
|
|||
md-5 = "0.10.5"
|
||||
once_cell = "1.9.0"
|
||||
reqwest = { version = "0.11.6", features = ["cookies", "json"] }
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
rocket = { version = "0.5.0-rc.3", features = ["json"] }
|
||||
thiserror = "1.0.38"
|
||||
url = "2.2.2"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.68"
|
||||
vergen = { version = "7.5.0", default_features = false, features = ["build", "git"] }
|
||||
vergen = { version = "8.1.1", features = ["build", "git", "gitcl"] }
|
||||
|
||||
[package.metadata.deb]
|
||||
maintainer = "Paul van Tilburg <paul@luon.net>"
|
||||
|
|
|
@ -7,13 +7,16 @@
|
|||
FROM docker.io/rust:1 as builder
|
||||
|
||||
# Build the dependencies first
|
||||
ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
|
||||
RUN USER=root cargo new --bin /usr/src/solar-grabber
|
||||
WORKDIR /usr/src/solar-grabber
|
||||
COPY ./Cargo.* ./
|
||||
RUN sed -i -e 's/^build =/#build =/' Cargo.toml
|
||||
RUN cargo build --release
|
||||
RUN rm src/*.rs
|
||||
|
||||
# Add the real project files from current folder
|
||||
COPY ./Cargo.toml ./
|
||||
ADD . ./
|
||||
|
||||
# Build the actual binary from the copied local files
|
||||
|
|
10
build.rs
10
build.rs
|
@ -1,7 +1,9 @@
|
|||
use anyhow::Result;
|
||||
use vergen::{vergen, Config};
|
||||
use std::error::Error;
|
||||
use vergen::EmitBuilder;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
// Generate the `cargo:` instructions to fill the appropriate environment variables.
|
||||
vergen(Config::default())
|
||||
EmitBuilder::builder().all_build().all_git().emit()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ impl VersionInfo {
|
|||
/// Retrieves the version information from the environment variables.
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
version: String::from(env!("VERGEN_BUILD_SEMVER")),
|
||||
version: String::from(env!("CARGO_PKG_VERSION")),
|
||||
timestamp: String::from(env!("VERGEN_BUILD_TIMESTAMP")),
|
||||
git_sha: String::from(&env!("VERGEN_GIT_SHA")[0..7]),
|
||||
git_timestamp: String::from(env!("VERGEN_GIT_COMMIT_TIMESTAMP")),
|
||||
|
@ -142,7 +142,7 @@ pub fn setup() -> Rocket<Build> {
|
|||
.attach(AdHoc::on_liftoff("Version", |_| {
|
||||
Box::pin(async move {
|
||||
let name = env!("CARGO_PKG_NAME");
|
||||
let version = env!("VERGEN_BUILD_SEMVER");
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let git_sha = &env!("VERGEN_GIT_SHA")[0..7];
|
||||
|
||||
println!("☀️ Started {name} v{version} (git @{git_sha})");
|
||||
|
|
|
@ -92,14 +92,17 @@ impl super::Service for Service {
|
|||
/// It mainly stores the acquired cookie in the client's cookie jar. The login credentials come
|
||||
/// from the loaded configuration (see [`Config`]).
|
||||
async fn login(&mut self) -> Result<()> {
|
||||
let login_url = login_url().expect("valid login URL");
|
||||
let params = [
|
||||
("username", &self.config.username),
|
||||
("password", &self.config.password),
|
||||
];
|
||||
let login_url = login_url().expect("valid login URL");
|
||||
self.client.post(login_url).form(¶ms).send().await?;
|
||||
|
||||
Ok(())
|
||||
let response = self.client.post(login_url).form(¶ms).send().await?;
|
||||
match response.error_for_status() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) if e.status() == Some(StatusCode::UNAUTHORIZED) => Err(Error::NotAuthorized),
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves a status update from the API of the My Autarco site.
|
||||
|
|
|
@ -9,6 +9,22 @@ use crate::{
|
|||
STATUS,
|
||||
};
|
||||
|
||||
/// The default sleep interval to use between checks.
|
||||
const DEFAULT_SLEEP_INTERVAL: u64 = 10;
|
||||
|
||||
/// The sleep interval upper limit when applying exponential backoff.
|
||||
const MAX_SLEEP_INTERVAL: u64 = 320;
|
||||
|
||||
/// The backoff factor.
|
||||
const BACKOFF_FACTOR: f64 = 2.0;
|
||||
|
||||
/// Calculates the new interval by applying the backoff factor and taking the maximum into account.
|
||||
fn back_off(interval: u64) -> u64 {
|
||||
let new_interval = (interval as f64 * BACKOFF_FACTOR) as u64;
|
||||
|
||||
new_interval.min(MAX_SLEEP_INTERVAL)
|
||||
}
|
||||
|
||||
/// Main update loop that logs in and periodically acquires updates from the API.
|
||||
///
|
||||
/// It updates the mutex-guarded current update [`Status`](crate::Status) struct which can be
|
||||
|
@ -23,9 +39,10 @@ pub(super) async fn update_loop(service: Services) -> color_eyre::Result<()> {
|
|||
|
||||
let mut last_updated = 0;
|
||||
let poll_interval = service.poll_interval();
|
||||
let mut sleep_interval = DEFAULT_SLEEP_INTERVAL;
|
||||
loop {
|
||||
// Wake up every 10 seconds and check if an update is due.
|
||||
sleep(Duration::from_secs(10)).await;
|
||||
sleep(Duration::from_secs(sleep_interval)).await;
|
||||
|
||||
let timestamp = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
|
@ -39,15 +56,24 @@ pub(super) async fn update_loop(service: Services) -> color_eyre::Result<()> {
|
|||
Ok(status) => status,
|
||||
Err(Error::NotAuthorized) => {
|
||||
eprintln!("💥 Update unauthorized, trying to log in again...");
|
||||
service.login().await?;
|
||||
if let Err(e) = service.login().await {
|
||||
eprintln!("💥 Login failed: {e}; will retry in {sleep_interval} seconds...");
|
||||
sleep_interval = back_off(sleep_interval);
|
||||
continue;
|
||||
};
|
||||
println!("⚡ Logged in successfully!");
|
||||
sleep_interval = DEFAULT_SLEEP_INTERVAL;
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("💥 Failed to update status: {}", e);
|
||||
eprintln!(
|
||||
"💥 Failed to update status: {e}; will retry in {sleep_interval} seconds..."
|
||||
);
|
||||
sleep_interval = back_off(sleep_interval);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
sleep_interval = DEFAULT_SLEEP_INTERVAL;
|
||||
last_updated = timestamp;
|
||||
|
||||
println!("⚡ Updated status to: {:#?}", status);
|
||||
|
|
Loading…
Reference in New Issue