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

Polish Token and OAuth #185

Merged
merged 28 commits into from
Feb 17, 2021
Merged

Conversation

ramsayleung
Copy link
Owner

@ramsayleung ramsayleung commented Feb 14, 2021

Description

As @Kestrer pointed out in #127, the expires_at and expires_in are not that easy to use:

TokenInfo stores expires_in as a u32, and additionally has the expires_at field. This is not easy to use, instead it should have a single expires field with the type Instant

There is no way to store expires information into a signle field, since the response of requesting to Spotify for an access token looks like this:

{
   "access_token": "NgCXRK...MzYjw",
   "token_type": "Bearer",
   "scope": "user-read-private user-read-email",
   "expires_in": 3600,
   "refresh_token": "NgAagA...Um_SHo"
}

It's possible to deserialize this expires_in to Token.expire field, like this:

    pub fn deserialize<'de, D>(deserializer: D) -> Result<Instant, D::Error>
    where
        D: Deserializer<'de>,
    {
        let elapsed = u32::deserialize(deserializer)?;
        let duration = Duration::from_secs(elapsed as u64);
        let now = Instant::now();
        let instant = now
            .checked_sub(duration)
            .ok_or_else(|| Error::custom("Erreur checked_add"))?;
        Ok(instant)
    }

In order to convert expires_in(elapsed) to Instant, it's necessory to instantiate a Instant object in deserialize function, it turns out to be a stateful function. If we serialize the Token into cache file and deserialize it to Token, then the expires value will change unexpectedly.

Hence, it's necessary to keep two fields(expires_in, expires_at) to handle expire information, the expires_in has been updated from u32 to std::time::Duration, and the expires_at field has been updated from u64 to chrono::DateTime.

For more details about the support of serde for std::time::Instant, check this issue: serde-rs/serde#1375

Motivation and Context

To make rspotify ergonomic to use. Modification:

  • Change Token.expires_in from u32 to std::time::Duration
  • Change Token.expires_at from i64 to chrono::DateTime<Utc>
  • Change Token.scope from String to HashSet.
  • Change OAuth.scope from String to HashSet.

Dependencies

None

Type of change

Please delete options that are not relevant.

  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • test_write_token
  • test_token_is_expired

@ramsayleung ramsayleung changed the title Polish the expires_at, expires_in fields Polish Token and OAuth Feb 14, 2021
@marioortizmanero marioortizmanero force-pushed the ramsay_optimize_expire_field branch from dd2331c to 21a5e5e Compare February 14, 2021 13:43
Copy link
Collaborator

@marioortizmanero marioortizmanero left a comment

Choose a reason for hiding this comment

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

Great job! I've just included a few commits to have neater iterators for converting between HashSet and Vec, and a few other improvements, although if you consider any of them let me know and revert them.

src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
@ramsayleung
Copy link
Owner Author

ramsayleung commented Feb 15, 2021

I've just included a few commits to have neater iterators for converting between HashSet and Vec, and a few other improvements, although if you consider any of them let me know and revert them.

You do a great job to reduce unnecessary operation, it's no way to revert them :)

PS: Perhaps you could take time to review this PR #184 if you are free, it fix some failed CI jobs, then we could merge master branch into current PR later to fix the failed CI.

src/oauth2.rs Outdated Show resolved Hide resolved
@ramsayleung ramsayleung mentioned this pull request Feb 15, 2021
87 tasks
@ramsayleung
Copy link
Owner Author

@marioortizmanero you could take time to review this PR again, I think the required commits are completed :)

Copy link
Collaborator

@marioortizmanero marioortizmanero left a comment

Choose a reason for hiding this comment

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

Ok after these comments it should be good to go!

Another thing I would like to consider is whether we'd be better off using BTreeSet instead of HashSet or not. Here's a comparison I've read: https://stackoverflow.com/questions/62558996/what-is-the-time-complexity-of-iterating-btreeset-and-hashset. This is also interesting: https://doc.rust-lang.org/std/collections/index.html#when-should-you-use-which-collection

What we mainly need is:

  • Iteration of the elements
  • Inserting new elements

It does look like a HashSet is the best way to go, but I just wanted to make sure.

examples/webapp/src/main.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
src/oauth2.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@marioortizmanero marioortizmanero left a comment

Choose a reason for hiding this comment

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

LGTM! Great work

@marioortizmanero marioortizmanero merged commit d3e3a1f into master Feb 17, 2021
@marioortizmanero marioortizmanero deleted the ramsay_optimize_expire_field branch February 17, 2021 09:24
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