-
Notifications
You must be signed in to change notification settings - Fork 65
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
Add support for authentication flows #1354
Conversation
I think that I would use a sealed interface, as we do with the other change notification interfaces. I would also remove the boolean as the status is already defined by the type of instance received. Naming is hard, I cannot think on something better, maybe we could shorten it to public sealed interface AuthChange {
public val user: User
}
public interface LoggedIn: AuthChange
public interface LoggedOut: AuthChange
public interface Removed: AuthChange
app.authChangeAsFlow().collect { change: AuthChange ->
when(change) {
is LoggedIn -> handleLogin(change.user)
is LoggedOut -> handleLogout(change.user)
is Removed -> handleRemove(change.user)
}
} I would leave it as simple as possible, we could add the booleans later on if required. |
PR should now reflect our discussion and is ready for review. |
packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/AuthenticationChange.kt
Outdated
Show resolved
Hide resolved
} | ||
} | ||
|
||
private suspend fun reportUserLoggedIn(user: User) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would have put the dispatching logic in one method
fun reportAuthenticationChange(event: AuthenticationChange) { ... }
and just create the events on the fly
reportAuthenticationChange(LoggedInImpl(user))
Instead of having separate methods for each. This would also make it easier to have common logic if we fail to send the events to the flow ... which I also think we would need, right? 🤔 (We have a utility checkForBufferOverFlow
to handle this uniformly for channels, but don't know how to fit that in here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have merged the different methods.
We are emitting events inside a suspend function and the flow is suspending, so I don't think we need to use checkForBufferOverFlow
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I guess you are right that we are just suspending if the recipient is not ready ... But is what we want? Would be quite tricky to see that the login/logout is blocked due to the observer of the authencationChangeAsFlow()
-flow being locked. Don't know if there is an easy way to channel the flow to follow the approach from our other flows. This is also way less active, so maybe just fine by adding some buffer space ... or is it then even less likely to spot if it doesn't happen on every emit
and we don't throw if the buffer is full 🤔
@@ -94,6 +94,7 @@ public class UserImpl( | |||
} | |||
|
|||
override suspend fun logOut() { | |||
val reportLoggedOut = loggedIn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not really safe. Two threads calling this simultaneous would issue two events but should only emit one. I guess we would either need a return value from core or synchronize the operations for a use. Don't know if it is a critical issue though. Same for the other events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I already created realm/realm-core#6516 which will also fix this. I'll think and see if there is something we can do to prevent this, but if it is super tricky I would probably just ignore this case. I doubt this is code that will see race conditions anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reworked the logic a little bit. The chance for a race condition should be less now, although still present. My stance would probably be that using locks for this would be overkill and we should wait for realm/realm-core#6516 for a proper fix, but not sure what you think?
Also, worst case you will see two logouts in a row (or something like that), but given that we don't promise anything about the state of the User object either, I don't think that is a big problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds ok to leave it as is for now. Maybe include a link to the core issue in a comment above reportLoggedOut
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great, added some minor comments on documentation. Happy on green on CI.
packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/AuthenticationChange.kt
Outdated
Show resolved
Hide resolved
packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/AuthenticationChange.kt
Show resolved
Hide resolved
packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/AuthenticationChange.kt
Outdated
Show resolved
Hide resolved
...rary-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/internal/AuthenticationChangeImpl.kt
Show resolved
Hide resolved
packages/library-sync/src/commonMain/kotlin/io/realm/kotlin/mongodb/App.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a bit pedantic, but I guess all APIs hitting the new authentication change updating-operations (login
, logout
, delete
and remove
) that in rare circumstances could throw due to buffer overrun needs a @throws IllegalStateException
-doc entry.
Also some unaddressed leftover comments from Clemente
Otherwise LGTM
Closes #749
Opening this PR with a few design decisions we need to agree on:
AuthenticationChange
with aAuthenticationChange.Type
change. Is that a good approach? There exist two alternatives: 1) Instead reuse theUser.State
which has the same semantics 2) Our object notifications use sealed classes, should we do this instead? Which would also allow us to remove theType
enum? I'm probably slightly leaning toward this alternative.authenticationChangeAsFlow
mirrors, kinda, theSyncSession.connectionStateAsFlow()
as API, not sure if a better name exists?EDIT: After discussion we went with this API: