Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update dependencies & stricter clippy #1

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
[workspace]

resolver = "2"

members = [
"spotflow",
"spotflow-c",
Expand Down
3 changes: 3 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
allow-expect-in-tests = true
allow-unwrap-in-tests = true
doc-valid-idents = ["IoT", "SQLite", ".."]
6 changes: 3 additions & 3 deletions spotflow-c/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ crate-type = ["cdylib", "staticlib"]
spotflow = { path = "../spotflow", version = "0.7.0", features = ["openssl-vendored"] }
anyhow = "1.0.57"
chrono = "0.4.20"
simple_logger = { version = "4.3.0", features = ["stderr"] }
http = "0.2.6"
simple_logger = { version = "5.0.0", features = ["stderr"] }
http = "1.1.0"
# Used because stable std does not have c_size_t
libc = "0.2.121"
log = "0.4.16"

[build-dependencies]
cbindgen = "0.21.0"
cbindgen = "0.26.0"
2 changes: 1 addition & 1 deletion spotflow-py/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ crate-type = ["cdylib"]
[dependencies]
chrono = "0.4.19"
spotflow = { path = "../spotflow", version = "0.7.0", features = ["openssl-vendored"] }
http = "0.2.8"
http = "1.1.0"
log = "0.4.17"
pyo3 = { version = "0.19.0", features = ["extension-module", "serde", "abi3-py37"] }
pyo3-log = "0.8.2"
Expand Down
14 changes: 7 additions & 7 deletions spotflow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,33 @@ openssl-vendored = ["openssl/vendored"]
[dependencies]
anyhow = "1.0.56"
async-trait = "0.1.61"
brotli = "3.3.4"
brotli = "6.0.0"
chrono = { version = "0.4.19", features = ["serde"] }
http = "0.2.6"
json-patch = "0.2.6"
http = "1.1.0"
json-patch = "2.0.0"
log = "0.4.16"
native-tls = "0.2.8"
openssl = { version = "0.10.29", optional = true }
rumqttc = { package = "spotflow-rumqttc-fork", version = "0.12.0", features = ["use-native-tls"], default-features = false }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
sqlx = { version = "0.6.2", features = ["sqlite", "chrono", "macros", "runtime-tokio-native-tls", "offline"] }
sqlx = { version = "0.7.4", features = ["sqlite", "chrono", "macros", "runtime-tokio", "tls-native-tls"] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that sqlx changed the format of its offline query metadata - instead of using the single file sqlx-data.json they now save the queries as individual files to the .sqlx directory. Therefore, the CI build fails now. Can you please run cargo sqlx prepare in the spotflow directory (you'll probably need to run cargo install [email protected] before that) and then commit all the generated files? And also delete sqlx-data.json?

Btw. I'd like to investigate if it wouldn't be easier to just use dev.db on CI as well so that we could get rid of calling cargo sqlx prepare altogether. Do you think it would work? Or are there any problems you encountered when working on this earlier?

thiserror = "1.0.30"
time = "0.3.36"
tokio = { version = "1.17.0", features = ["rt", "sync", "macros"] }
tokio = { version = "1.17.0", features = ["rt", "sync", "macros", "rt-multi-thread"] }
tokio-util = "0.7.1"
ureq = { version = "2.4.0", features = ["json", "native-tls"], default-features = false }
urlencoding = "2.1.0"
uuid = { version = "1.0.0", features = ["v4"] }

[build-dependencies]
tokio = { version = "1.17.0", features = ["rt"] }
sqlx = { version = "0.6.2", features = ["sqlite", "runtime-tokio-native-tls"] }
sqlx = { version = "0.7.4", features = ["sqlite", "runtime-tokio-native-tls"] }

[dev-dependencies]
azure_core = "0.1.1"
azure_identity = "0.1.1"
env_logger = "0.9.0"
env_logger = "0.11.0"
azure_storage = "0.1.0"
azure_storage_blobs = "0.1.0"
oauth2 = "4.1.0"
Expand Down
2 changes: 2 additions & 0 deletions spotflow/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel = "1.80.1"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any advantage of setting the toolchain to a fixed version? We currently always use the current version in CI (i.e. the version installed on the current runner) and AFAIK it works quite well. For example, we don't have to think about updating the toolchain manually. But maybe there's something I'm missing.

15 changes: 6 additions & 9 deletions spotflow/src/cloud/api_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub(crate) fn put(
token: impl AsRef<str>,
data: impl serde::Serialize,
) -> Result<Response, RequestError> {
send(http::Method::PUT, base_uri, relative_uri, token, data)
send(&http::Method::PUT, base_uri, relative_uri, token, data)
}

pub(crate) fn post(
Expand All @@ -53,21 +53,18 @@ pub(crate) fn post(
token: impl AsRef<str>,
data: impl serde::Serialize,
) -> Result<Response, RequestError> {
send(http::Method::POST, base_uri, relative_uri, token, data)
send(&http::Method::POST, base_uri, relative_uri, token, data)
}

pub(crate) fn send(
method: http::Method,
method: &http::Method,
base_uri: &Uri,
relative_uri: &Uri,
token: impl AsRef<str>,
data: impl serde::Serialize,
) -> Result<Response, RequestError> {
let authority = match base_uri.authority() {
Some(authority) => authority,
None => {
return Err(anyhow!("Provided base URI {base_uri:?} does not contain the authority (e.g., 'api.eu1.spotflow.io').").into())
}
let Some(authority) = base_uri.authority() else {
return Err(anyhow!("Provided base URI {base_uri:?} does not contain the authority (e.g., 'api.eu1.spotflow.io').").into());
};
let path = relative_uri.path_and_query();

Expand All @@ -89,7 +86,7 @@ pub(crate) fn send(
Arc::new(native_tls::TlsConnector::new().expect("Unable to build TLS connector"));
let agent = ureq::AgentBuilder::new().tls_connector(connector).build();

let request = match method {
let request = match *method {
http::Method::POST => agent.post(&uri.to_string()),
http::Method::PUT => agent.put(&uri.to_string()),
_ => unimplemented!("Method {} is not implemented.", method),
Expand Down
12 changes: 6 additions & 6 deletions spotflow/src/cloud/dps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ impl Provisioning {
})?
.into_json()
.context("Failed deserializing response from JSON")
.map_err(|e| e.into())
.map_err(Into::into)
}

pub fn complete(&mut self, operation_id: &str) -> Result<RegistrationToken, CompletionError> {
Expand Down Expand Up @@ -192,7 +192,7 @@ pub fn refresh(
})?
.into_json()
.context("Failed deserializing response from JSON")
.map_err(|e| e.into())
.map_err(Into::into)
}

#[cfg(test)]
Expand Down Expand Up @@ -226,7 +226,7 @@ mod tests {
instance_uri = format!("https://{instance_uri}");
}

let instance_url: Uri = instance_uri
let instance_uri: Uri = instance_uri
.parse()
.expect("Invalid instance URL: '{instance_uri}'");

Expand All @@ -235,7 +235,7 @@ mod tests {
);
let pt = ProvisioningToken { token: pt };

let mut provisioning = Provisioning::new(instance_url.clone(), pt);
let mut provisioning = Provisioning::new(instance_uri.clone(), pt);
provisioning.with_device_id(device_id);
let init = provisioning
.init()
Expand All @@ -251,7 +251,7 @@ mod tests {
assert!(matches!(result, Err(CompletionError::NotReady)));

// Approve will normally happen out of band by manual operator calls
approve_provisioning(&instance_url, &workspace_id, &operation)
approve_provisioning(&instance_uri, &workspace_id, &operation)
.expect("Unable to approve operation");

let result = provisioning.complete(&operation);
Expand All @@ -275,7 +275,7 @@ mod tests {
expiration: result.expiration,
};

let res = register(&instance_url, &rt).expect("Unable to register device.");
let res = register(&instance_uri, &rt).expect("Unable to register device.");
println!("{res:#?}");
}

Expand Down
35 changes: 10 additions & 25 deletions spotflow/src/cloud/drs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ impl RegistrationResponse {
bail!("Cannot parse anything but Shared Access Signature.");
}

let device_id = self
.connection_string
self.connection_string
.split(';')
.find_map(|part| {
if let Some((k, v)) = part.split_once('=') {
Expand All @@ -55,31 +54,20 @@ impl RegistrationResponse {
}
None
})
.unwrap();

Ok(device_id)
.context("Connection string does not contain `DeviceId`.")
}

pub fn workspace_id(&self) -> Result<&str> {
let iot_hub_device_id = self.iot_hub_device_id()?;

let separator_pos = Self::get_iot_hub_device_id_separator_pos(iot_hub_device_id)?;

Ok(&iot_hub_device_id[..separator_pos])
Ok(self.split_iot_hub_device_id()?.0)
}

pub fn device_id(&self) -> Result<&str> {
let iot_hub_device_id = self.iot_hub_device_id()?;

let separator_pos = Self::get_iot_hub_device_id_separator_pos(iot_hub_device_id)?;

Ok(&iot_hub_device_id[separator_pos + 1..])
Ok(self.split_iot_hub_device_id()?.1)
}

fn get_iot_hub_device_id_separator_pos(
iot_hub_device_id: &str,
) -> Result<usize, anyhow::Error> {
iot_hub_device_id.find(':').ok_or_else(|| {
fn split_iot_hub_device_id(&self) -> Result<(&str, &str), anyhow::Error> {
let iot_hub_device_id = self.iot_hub_device_id()?;
iot_hub_device_id.split_once(':').ok_or_else(|| {
anyhow::anyhow!("Unknown format of IoT Hub Device ID, it does not contain a colon: '{iot_hub_device_id}'.")
})
}
Expand All @@ -89,8 +77,7 @@ impl RegistrationResponse {
bail!("Cannot parse anything but Shared Access Signature.");
}

let sas = self
.connection_string
self.connection_string
.split(';')
.find_map(|part| {
if let Some((k, v)) = part.split_once('=') {
Expand All @@ -100,9 +87,7 @@ impl RegistrationResponse {
}
None
})
.unwrap();

Ok(sas)
.context("Connection string does not contain `SharedAccessSignature`.")
}
}

Expand All @@ -126,5 +111,5 @@ pub fn register(
})?
.into_json()
.context("Failed deserializing response from JSON")
.map_err(|e| e.into())
.map_err(Into::into)
}
12 changes: 9 additions & 3 deletions spotflow/src/cloud/duration_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,13 @@ impl<'de> Visitor<'de> for DurationVisitor {
let hours: u64;
// let mut microseconds = 0;

let parts: Vec<&str> = s.split(':').collect();
let parts: [&str; 3] = s.split(':').collect::<Vec<_>>().try_into().map_err(|_| {
de::Error::invalid_value(
Unexpected::Str("Duration did not contain two colons."),
&self,
)
})?;

let day_and_hour = parts[0];
let minutes: u64 = parts[1].parse().map_err(|_| {
de::Error::invalid_value(
Expand Down Expand Up @@ -131,7 +137,7 @@ mod tests {
fn deser_duration() {
let s = "\"8.11:55:36.3296177\"";
let d: Duration = serde_json::from_str::<DurationWrapper>(s).unwrap().into();
assert_eq!(d.as_secs(), 734136);
assert_eq!(d.as_secs(), 734_136);
}

#[test]
Expand All @@ -156,7 +162,7 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(expected = "This duration cannot be deserialized.")]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests fails because the string "This duration cannot be deserialized." isn't a substring of the actual error message. I suggest either changing the string to "Duration did not contain two colons." or removing it.

fn deser_duration_fail() {
let s = "\"10:39\"";
let _d: Duration = serde_json::from_str::<DurationWrapper>(s).unwrap().into();
Expand Down
5 changes: 5 additions & 0 deletions spotflow/src/ingress/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ impl DeviceClientBuilder {

/// Hidden from the documentation because the concept of Sites and their IDs is not yet explained in the Platform documentation.
#[doc(hidden)]
#[must_use]
pub fn with_site_id(mut self, site_id: String) -> DeviceClientBuilder {
self.site_id = Some(site_id);
self
Expand All @@ -132,6 +133,7 @@ impl DeviceClientBuilder {
///
/// If your company uses a dedicated instance of the Platform, such as `acme.spotflow.io`, specify it here.
/// The default value is `api.eu1.spotflow.io`.
#[must_use]
pub fn with_instance(mut self, instance: String) -> DeviceClientBuilder {
self.instance = Some(instance);
self
Expand All @@ -140,6 +142,7 @@ impl DeviceClientBuilder {
/// Set the callback to display the details of the
/// [Provisioning Operation](https://docs.spotflow.io/connect-devices/#provisioning-operation)
/// when [`DeviceClientBuilder::build`] is performing [Device Provisioning](https://docs.spotflow.io/connect-devices/#device-provisioning).
#[must_use]
pub fn with_display_provisioning_operation_callback(
mut self,
callback: Box<dyn ProvisioningOperationDisplayHandler>,
Expand All @@ -153,6 +156,7 @@ impl DeviceClientBuilder {
/// [Device](https://docs.spotflow.io/connect-devices/#device) receives their update from the Platform.
/// The [Device configuration tutorial](https://docs.spotflow.io/configure-devices/tutorial-configure-device#1-start-device)
/// shows how to use this option. The callback must be `Send` and `Sync`, because it's called in a separate thread.
#[must_use]
pub fn with_desired_properties_updated_callback(
mut self,
callback: Box<dyn DesiredPropertiesUpdatedCallback>,
Expand All @@ -162,6 +166,7 @@ impl DeviceClientBuilder {
}

/// Set the source of the system signals that can request the process to stop.
#[must_use]
pub fn with_signals_source(mut self, signals_src: Box<dyn ProcessSignalsSource>) -> Self {
self.signals_src = Some(signals_src);
self
Expand Down
6 changes: 6 additions & 0 deletions spotflow/src/ingress/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub struct MessageContext {
impl MessageContext {
// Create a new instance of [`MessageContext`] with the provided [Stream Group](https://docs.spotflow.io/send-data/#stream-group)
// and [Stream](https://docs.spotflow.io/send-data/#stream).
#[must_use]
pub fn new(stream_group: Option<String>, stream: Option<String>) -> Self {
Self {
stream_group,
Expand All @@ -67,6 +68,7 @@ impl MessageContext {

/// Get the [Stream Group](https://docs.spotflow.io/send-data/#stream-group) where
/// [Messages](https://docs.spotflow.io/send-data/#message) will be sent to.
#[must_use]
pub fn stream_group(&self) -> Option<&str> {
self.stream_group.as_deref()
}
Expand All @@ -79,6 +81,7 @@ impl MessageContext {

/// Get the [Stream](https://docs.spotflow.io/send-data/#stream) where
/// [Messages](https://docs.spotflow.io/send-data/#message) will be sent to.
#[must_use]
pub fn stream(&self) -> Option<&str> {
self.stream.as_deref()
}
Expand All @@ -90,6 +93,7 @@ impl MessageContext {
}

/// Get the compression to use for sending [Messages](https://docs.spotflow.io/send-data/#message).
#[must_use]
pub fn compression(&self) -> Option<Compression> {
self.compression.clone()
}
Expand Down Expand Up @@ -338,6 +342,7 @@ impl DeviceClient {
/// if their version is higher than `version`. Otherwise, return `None`.
///
/// Only the latest version is returned, any versions between the last obtained one and the current one are skipped.
#[must_use]
pub fn desired_properties_if_newer(&self, version: u64) -> Option<DesiredProperties> {
self.connection.desired_properties_if_newer(version)
}
Expand Down Expand Up @@ -393,6 +398,7 @@ impl DeviceClient {
/// **Warning**: Deprecated, don't use.
#[deprecated]
#[doc(hidden)]
#[must_use]
pub fn reported_properties(&self) -> Option<String> {
self.connection.reported_properties()
}
Expand Down
Loading
Loading