-
Notifications
You must be signed in to change notification settings - Fork 72
Add completed_event_id FK to prevent session replay #1158
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
base: master
Are you sure you want to change the base?
Conversation
Pull Request Test Coverage Report for Build 18983609771Details
💛 - Coveralls |
|
Thank you for taking on this @Mshehu5 . on first pass , this works as intended |
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.
The application should just need to properly implement the close() method to set the column appropriately, as close() is called by the payjoin state machine when appropriate; the application should never call save_event() directly. This makes me realize the documentation around the SessionPersister methods needs to be clearer.
c0fd47a to
de46c09
Compare
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.
Not a huge fan of using string matching to find the "closed" event and left some other suggestions.
fbe10e6 to
4866994
Compare
4866994 to
b7c8741
Compare
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.
Its not clear to me what problem the changes in payjoin/src/core/send/v2 and its corresponding change in payjoin-cli are solving. They seem unrelated to the original ticket and should be moved to a different PR once its clear what the problem actually is.
payjoin-cli/src/db/v2.rs
Outdated
| "UPDATE send_sessions SET completed_at = ?1 WHERE session_id = ?2", | ||
| params![now(), *self.session_id], | ||
| "UPDATE send_sessions SET completed_at = ?1, completed_event_id = ?2 WHERE session_id = ?3", | ||
| params![now(), completed_event_id, *self.session_id], |
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.
What happens is completed_event_id is None? There should will always be a session event before close is called. Should we make this expectation explicit?
understood, seems the reason I made the change in |
dad306d to
f02b04b
Compare
f02b04b to
622a6c6
Compare
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.
Just a few more things. Mainly noticing some unrelated changes
| "SELECT r.session_id, e.created_at | ||
| FROM receive_sessions r | ||
| JOIN receive_session_events e ON r.completed_event_id = e.id | ||
| WHERE r.completed_event_id IS NOT NULL", |
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 don't think this join is neccecary. A session is active until completed_event_id is not null.
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.
You’re right if we’re only fetching inactive sessions, this approach will work. However, from what I’ve observed in the codebase, the get_inactive_send_session_ids() function uses the completed_at timestamp, which is needed for the payjoin-cli history command (see payjoin-cli/src/app/v2, lines 384–409).
The reason for the join is to retrieve the created_at timestamp of the event that closed the session, which serves as the completed_at timestamp.
This is just an observation I might be wrong. If a change is needed to accommodate this, I can include it in this PR or a follow-up one.
| "SELECT session_id, completed_at FROM send_sessions WHERE completed_at IS NOT NULL", | ||
| "SELECT s.session_id, e.created_at | ||
| FROM send_sessions s | ||
| JOIN send_session_events e ON s.completed_event_id = e.id |
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.
Same thing here
| let conn = self.db.get_connection()?; | ||
| let mut stmt = conn.prepare( | ||
| "SELECT event_data FROM send_session_events WHERE session_id = ?1 ORDER BY created_at ASC", | ||
| "SELECT event_data FROM send_session_events WHERE session_id = ?1 ORDER BY id ASC", |
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.
Since the ID is always auto-incremeneting, i think this would work. But why make this change? It seems unrelated to original intent of the PR. AFAICT created_at should still be a field on send_session_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.
The reason for this change is I noticed events saved within the same second share the same created_at (seconds precision), making created_at non-deterministic and causing out-of-order result
I aslo wanted to add DB transaction to make it more atomic but I think it will be better for a followup PR as it is out of scope
| "SELECT event_data FROM receive_session_events WHERE session_id = ?1 ORDER BY created_at ASC", | ||
| "SELECT event_data FROM receive_session_events WHERE session_id = ?1 ORDER BY id ASC", |
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.
Same thing here.
Add completed_event_id foreign key columns to both send_sessions and receive_sessions tables that reference the exact event that closed the session to replace completed_at column.
622a6c6 to
37aa822
Compare
payjoin-cli/src/db/v2.rs
Outdated
| if matches!(event, SenderSessionEvent::Closed(_)) { | ||
| conn.execute( | ||
| "UPDATE send_sessions SET completed_at = ?1, completed_event_id = ?2 WHERE session_id = ?3", | ||
| params![now(), event_id, *self.session_id], |
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.
The time here would be inacurrate for when the actual session event was created . No need to call now() again here . Rather use the time when the actual session_event was created as this just tells us the time this DB entry was made
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.
Thanks for the review Zealsham!
It seems your comments are based on an older version of this PR. I’d really appreciate it if you could take a look at the latest changes as well.
This PR adds completed_event_id foreign key columns to both send_sessions and receive_sessions tables. This column references the exact event row that closed the session.
Closes #1146
Please confirm the following before requesting review:
AI
in the body of this PR.