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

feat: Add database tracking and report for Push Reliability #769

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

jrconlin
Copy link
Member

@jrconlin jrconlin commented Sep 25, 2024

This PR introduces tracking throughput for the database.

It also introduces the PushReliability reporting skeleton. This will be
fleshed out with full reporting later.

Closes: #SYNC-4324

This PR introduces tracking throughput for the database.

It also introduces the PushReliability reporting skeleton. This will be
fleshed out with full reporting later.

Closes: #SYNC-4324
@@ -34,3 +34,5 @@ ctor.workspace = true
tokio.workspace = true

autoconnect_common = { workspace = true, features = ["test-support"] }

Copy link
Member Author

Choose a reason for hiding this comment

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

these features will be used in the next PR.

@@ -310,7 +321,7 @@ mod tests {
#[test]
fn test_tracking_keys() -> ApiResult<()> {
let settings = Settings{
tracking_keys: r#"["BLMymkOqvT6OZ1o9etCqV4jGPkvOXNz5FdBjsAR9zR5oeCV1x5CBKuSLTlHon-H_boHTzMtMoNHsAGDlDB6X7vI"]"#.to_owned(),
tracking_keys: r#"["BLMymkOqvT6OZ1o9etCqV4jGPkvOXNz5FdBjsAR9zR5oeCV1x5CBKuSLTlHon-H_boHTzMtMoNHsAGDlDB6X7"]"#.to_owned(),
Copy link
Member Author

Choose a reason for hiding this comment

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

Modified to check for padding stripping.

Copy link
Contributor

@taddes taddes Oct 1, 2024

Choose a reason for hiding this comment

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

Should this one have the "==" added to end as well, with exclusion of vI?

Copy link
Member Author

Choose a reason for hiding this comment

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

If we were decoding the key from base64, yes. We're currently not doing that so just tweaking the string values to ensure that they match (with and without the padding) should be fine.

If we ever decide to decode these strings and do a byte comparison of the decoded pairs, then we would have to revisit this test, but that's out of scope for this PR.

jrconlin added a commit that referenced this pull request Sep 26, 2024
* This presumes that there's a redis like storage system that can record
  the state transitions of messages.
* function is hidden behind `reliable_report` feature flag
* Requires #769

Closes: SYNC-4419
@jrconlin jrconlin changed the title Feat/sync 4324 track db feat: Add database tracking and report for Push Reliability Sep 27, 2024
Copy link
Contributor

@taddes taddes left a comment

Choose a reason for hiding this comment

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

👍 thanks for the work on this. Some thoughts on adjustments

@@ -21,6 +21,12 @@ pub fn build_message_data(notification: &Notification) -> ApiResult<HashMap<&'st
message_data.insert_opt("enc", notification.headers.encryption.as_ref());
message_data.insert_opt("cryptokey", notification.headers.crypto_key.as_ref());
message_data.insert_opt("enckey", notification.headers.encryption_key.as_ref());
// Report the data to the UA. How this value is reported back is still a work in progress.
trace!(
"🔍 Sending Reliability: {:?}",
Copy link
Contributor

Choose a reason for hiding this comment

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

For clarity, I'd update this to

Suggested change
"🔍 Sending Reliability: {:?}",
"🔍 Sending Reliability ID: {:?}",

and perhaps the other instances this is logged

.is_trackable(&v)
.then(|| app_state.vapid_tracker.get_id(req.headers()))
});
debug!("🔍 Assigning Reliability: {:?}", reliability_id);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
debug!("🔍 Assigning Reliability: {:?}", reliability_id);
debug!("🔍 Assigning Reliability ID: {:?}", reliability_id);

if let Some(reliability_id) = &self.subscription.reliability_id {
map.insert(
"reliability_id",
serde_json::to_value(reliability_id).unwrap(),
Copy link
Contributor

Choose a reason for hiding this comment

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

I see the signature returns HashMap<&'static str, serde_json::Value> regardless of success/fail with the .unwrap() calls. Did we want to simplify this with the use of ? in a few places? Here's my thought:

Eg.

/// Serialize the notification for delivery to the connection server.
pub fn serialize_for_delivery(&self) -> Result<HashMap<&'static str, serde_json::Value>, serde_json::Error> {
    let mut map = HashMap::new();
    
    map.insert(
        "channelID",
        serde_json::to_value(self.subscription.channel_id)?
    );
    map.insert("version", serde_json::to_value(&self.message_id)?);
    map.insert("ttl", serde_json::to_value(self.headers.ttl)?);
    map.insert("topic", serde_json::to_value(&self.headers.topic)?);
    map.insert("timestamp", serde_json::to_value(self.timestamp)?);

    if let Some(reliability_id) = &self.subscription.reliability_id {
        map.insert("reliability_id", serde_json::to_value(reliability_id)?);
    }

    if let Some(data) = &self.data {
        map.insert("data", serde_json::to_value(data)?);

        let headers: HashMap<_, _> = self.headers.clone().into();
        map.insert("headers", serde_json::to_value(headers)?);
    }

    Ok(map)
}

Therefore the single call to this function in autoendpoint/src/routers/webpush.rs has a surrounding context to returning a Result type, so it'd probably be minimal adjustment with just calling a single .unwrap()

Copy link
Member Author

Choose a reason for hiding this comment

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

Fair. I didn't want to modify a bunch of extra things, but I think you're right. I'll update ApiErrorKind

@@ -85,6 +85,8 @@ pub struct ClientAck {
#[serde(rename = "channelID")]
pub channel_id: Uuid,
pub version: String,
#[serde(default)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps a comment - and potentially comments for channel_id and version, even if it's self evident - to describe purpose of the reliability_id

Comment on lines 178 to 182
let reply = Self::read_list_from_str(keys, "Invalid AUTOEND_TRACKING_KEYS")
.map(|v| v.to_owned().replace("=", ""))
.collect();
trace!("🔍 keys: {:?}", reply);
reply
Copy link
Contributor

Choose a reason for hiding this comment

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

minor nit, but thought result is better than reply since it's not calling out to anywhere? And making the trace output linked be a little more explicit, given keys might be a bit vague.

Suggested change
let reply = Self::read_list_from_str(keys, "Invalid AUTOEND_TRACKING_KEYS")
.map(|v| v.to_owned().replace("=", ""))
.collect();
trace!("🔍 keys: {:?}", reply);
reply
let result = Self::read_list_from_str(keys, "Invalid AUTOEND_TRACKING_KEYS")
.map(|v| v.to_owned().replace("=", ""))
.collect();
trace!("🔍 tracking_keys: {:?}", reply);
result

@@ -310,7 +321,7 @@ mod tests {
#[test]
fn test_tracking_keys() -> ApiResult<()> {
let settings = Settings{
tracking_keys: r#"["BLMymkOqvT6OZ1o9etCqV4jGPkvOXNz5FdBjsAR9zR5oeCV1x5CBKuSLTlHon-H_boHTzMtMoNHsAGDlDB6X7vI"]"#.to_owned(),
tracking_keys: r#"["BLMymkOqvT6OZ1o9etCqV4jGPkvOXNz5FdBjsAR9zR5oeCV1x5CBKuSLTlHon-H_boHTzMtMoNHsAGDlDB6X7"]"#.to_owned(),
Copy link
Contributor

@taddes taddes Oct 1, 2024

Choose a reason for hiding this comment

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

Should this one have the "==" added to end as well, with exclusion of vI?

"""Test delivery of a basic push message with a VAPID header."""
uuid_data: str = str(uuid.uuid4())
vapid_info = _get_vapid(key=TRACKING_KEY, payload=vapid_payload)
# quick sanity check to ensure that the keys match.
Copy link
Contributor

Choose a reason for hiding this comment

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

thanks for adding the useful comments here

Comment on lines +850 to +851
log.debug(f"🔍 reliability {result["reliability_id"]}")
assert result["reliability_id"] is not None
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor nit: switch order so after assertions and match debug string to reliability_id for clarity.

Suggested change
log.debug(f"🔍 reliability {result["reliability_id"]}")
assert result["reliability_id"] is not None
assert result["reliability_id"] is not None
log.debug(f"🔍 reliability_id {result["reliability_id"]}")

clean_header = registered_test_client._crypto_key.replace('"', "").rstrip("=")
assert result["headers"]["encryption"] == clean_header
assert result["data"] == base64url_encode(uuid_data)
assert result["messageType"] == "notification"
Copy link
Contributor

Choose a reason for hiding this comment

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

We have an enum of ClientMessageType in the async_push_test_client.py which you could add this as a variant, should you wish. Can alter this to simply be MessageType as well, since the "client" does double duty in these tests and isn't strictly the client...

Comment on lines +190 to +192
tracking_keys="[{}]".format(
base64.urlsafe_b64encode((b"\4" + TRACKING_PUB_KEY.to_string())).decode()
),
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
tracking_keys="[{}]".format(
base64.urlsafe_b64encode((b"\4" + TRACKING_PUB_KEY.to_string())).decode()
),
tracking_keys=f"[{base64.urlsafe_b64encode(b'\4' + TRACKING_PUB_KEY.to_string()).decode()}]",

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants