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

Refactor Guardian.DB.Sweeper #130

Merged
merged 3 commits into from
May 17, 2021
Merged

Refactor Guardian.DB.Sweeper #130

merged 3 commits into from
May 17, 2021

Conversation

doomspork
Copy link
Member

@doomspork doomspork commented May 16, 2021

I'd like to slowly start improving the code quality and test coverage across the Ueberauth org projects. Since we've been focusing on Guardian.DB recently I thought I'd start by proposing some changes here. For this PR I looked to tackle the Sweeper functionality first:

  1. We currently have Sweeper and SweeperServer but their roles are not clearly separated (Sweeper manages the SweeperServer's state for instance). I combined these together as there's no real benefit to keeping them separate and this cleans up some of their code.
  2. Updated the tests to use the GenServer directly and test the 2 major functions it provides: purge/0 and reset_timer/0.
  3. Moved the Sweeper from Guardian.DB.Token.SweeperServer to Guardian.DB.Sweeper, I'm not entirely sure why this was ever nested under Token but it seems rather unnecessary. This is a breaking change.
  4. Stop accessing configuration directly from the library code. It's generally a better practice for the application to have its own configuration which it passes in rather than libraries doing that themselves.

I may look at adding some addition test coverage for each of the GenServer callbacks just to cover our bases.

This PR is a place to start this conversation, hence the draft. 🎉

@sixty_minutes 60 * 60 * 1000

def start_link(opts) do
interval = Keyword.get(opts, :interval, @sixty_minutes)
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like it's : sweep_interval in the config, @doomspork

config :guardian, Guardian.DB,
  repo: MyApp.Repo, # Add your repository module
  schema_name: "guardian_tokens", # default
  token_types: ["refresh_token"], # store all token types if not set
  sweep_interval: 60 # default: 60 minutes

Copy link
Contributor

Choose a reason for hiding this comment

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

oh I got it now, so it's not configurable anymore?

Copy link
Member Author

@doomspork doomspork May 16, 2021

Choose a reason for hiding this comment

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

It is configurable @alexfilatov but as I mentioned in this point:

  1. Stop accessing configuration directly from the library code. It's generally a better practice for the application to have its own configuration which it passes in rather than libraries doing that themselves.

I think we should be moving away from our libraries accessing application configuration themselves directly. Applications should be able to pass in their configurations.

I'm open to not doing this, I think it's just a better design practice.

children = [
  ...
  {Guardian.DB.Sweeper, interval: configured_sweep_interval()}
  ... 
]

Copy link
Member

Choose a reason for hiding this comment

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

I love this part for sure

@yordis
Copy link
Member

yordis commented May 16, 2021

We currently have Sweeper and SweeperServer but their roles are not clearly separated (Sweeper manages the SweeperServer's state for instance). I combined these together as there's no real benefit to keeping them separate and this cleans up some of their code.

I disagree with the promise of no real benefits.

SweeperServer is impure, it deals with Erlang message passing and gen-server stuff. While Sweeper is pure since it is just the implementation of the Sweeper. Functional Core with Imperative Interface.

That being said, you are the boss.

I just would try to be clear on what is wrong as of today based on the objective issues since it wasn't been a problem so far before we start removing things just because it is deemed unimportant based on your skills set or your perspective, which it isn't hard to understand where you are coming from for sure. I totally understand your reasoning.

@yordis
Copy link
Member

yordis commented May 16, 2021

Overall, don't mind the changes, I can maintaining them either way, if you feel strong about it, you have my 1+

@doomspork
Copy link
Member Author

That being said, you are the boss.

It's not that at all. I'm open to ideas and suggestions.

just would try to be clear on what is wrong as of today based on the objective issues since it wasn't been a problem so far before we start removing things just because it is deemed unimportant based on your skills set or your perspective, which it isn't hard to understand where you are coming from for sure. I totally understand your reasoning.

I'm not sure "wasn't been a problem so far" is ever good reason to avoid changes, would we ever improve code with that mentality? If your concern is having to test the GenServers I can update the test to use the GenServer callbacks directly and avoid that. I actually want to test that this stuff works accordingly so these tests are intentional but I'm happy to remove them.

Simplifying the code to be easier to understand makes things better for everyone, especially us maintainers. A code base that's difficult to grok keeps contributors away.

I'm okay to not incorporating this change but I think it's misguided to assume that just because we can have "pure" functions to test that there isn't a better solution. As-is responsibility is spread throughout modules making understanding the code base far more complicated/

@yordis
Copy link
Member

yordis commented May 17, 2021

Works for me either way to me, I leave this one to your judgment, I trust your judgments.

@doomspork
Copy link
Member Author

Once #129 is merged I will update this further 👍

@doomspork doomspork marked this pull request as ready for review May 17, 2021 01:11
@doomspork
Copy link
Member Author

@yordis I updated the tests and made use of Mox for 2 reasons:

  1. Updated the tests to use the GenServer callbacks directly. This should address you concern with impure functions.
  2. Using Mox we can test the functionality works without having to actually interact with the database.

scheduled work.
"""
def purge do
GenServer.cast(__MODULE__, :sweep)
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 were also changed to cast from call since we don't need or care about a reply.

@doomspork doomspork requested a review from yordis May 17, 2021 01:13
@@ -0,0 +1,70 @@
defmodule Guardian.DB.Sweeper do
Copy link
Member Author

Choose a reason for hiding this comment

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

For backwards compatibility we could add a Guardian.DB.Token.SweeperServer alias but I'd like to encourage folks to move away from that module.

Copy link
Member

Choose a reason for hiding this comment

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

@doomspork wouldn't be better to use SweeperServer following some GenServer lingos?

It is a stateful thing (hint the server part of it) that you send messages to it 🤔 💭

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't often seen things called "Server" in Elixir/Erlang space, do you? Looking at a few of my applications there's nothing in the application tree with that suffix 🤔

Copy link
Member

Choose a reason for hiding this comment

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

It depends if you have the Server being the message passing, while the thing without Server (as it was before), was the implementation of the thing.

Dave has an amazing course about it, https://codestool.coding-gnome.com/courses/elixir-for-programmers

Copy link
Member Author

Choose a reason for hiding this comment

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

I appreciate Dave's pattern but as much as he would like to see this catch on I can't say I see this having gained any adoption. I prefer to keep code simple and easy to grok for the human reader over trying to be "academically right".

I'd like to leave this.

doomspork added 2 commits May 16, 2021 19:16
Moved the Sweeper functionality out from inside the Token
namespace/folder. Also simplified the code by combining the two separate
but unnecessary modules. Updated and added test coverage.
@doomspork doomspork merged commit e3a4c6b into master May 17, 2021
@doomspork doomspork deleted the refactor-sweeper branch May 17, 2021 13:30
@RichDom2185 RichDom2185 mentioned this pull request Sep 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants