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

Bug 1897264 - interruption support for ingestion #6246

Merged
merged 1 commit into from
May 20, 2024

Conversation

bendk
Copy link
Contributor

@bendk bendk commented May 16, 2024

Added an interrupt_everything method that interrupts both the read and write connection. This is intended for iOS to use to interrupt the suggest component during shutdown. See https://bugzilla.mozilla.org/show_bug.cgi?id=1897299 for a discussion on next steps here.

Created a new WriteScope type that stores an interrupt scope that can be used for multiple write calls. This allows the ingestion code to catch all interruptions that happened after the ingestion started. With the old system, if interrupt_everything was called in-between ingestion two types then we might miss it.

Pull Request checklist

  • Breaking changes: This PR follows our breaking change policy
    • This PR follows the breaking change policy:
      • This PR has no breaking API changes, or
      • There are corresponding PRs for our consumer applications that resolve the breaking changes and have been approved
  • Quality: This PR builds and tests run cleanly
    • Note:
      • For changes that need extra cross-platform testing, consider adding [ci full] to the PR title.
      • If this pull request includes a breaking change, consider cutting a new release after merging.
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Changelog: This PR includes a changelog entry in CHANGELOG.md or an explanation of why it does not need one
    • Any breaking changes to Swift or Kotlin binding APIs are noted explicitly
  • Dependencies: This PR follows our dependency management guidelines
    • Any new dependencies are accompanied by a summary of the due diligence applied in selecting them.

Branch builds: add [firefox-android: branch-name] to the PR title.

Sorry, something went wrong.

@bendk bendk requested review from ncloudioj and linabutler May 16, 2024 19:25
@@ -601,6 +639,8 @@ struct SuggestStoreDbs {
writer: SuggestDb,
/// A read-only connection used to query the database.
reader: SuggestDb,
/// A read-write connection used specifically for ingestion
ingestion: SuggestDb,
Copy link
Contributor Author

@bendk bendk May 16, 2024

Choose a reason for hiding this comment

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

I like the idea of adding a 3rd connection, but maybe we should wait on this. We could put out a quick fix for the iOS issue and tackle this separately. WDY2T?

Copy link
Contributor

@linabutler linabutler May 16, 2024

Choose a reason for hiding this comment

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

Oh, let's not have two read-write connections if we could, please...having multiple writers is a bag of hurt in SQLite. We unfortunately learned that the hard way with Rust Places, where we saw contention between the writer and syncer—and when we tried that on Desktop, we could even wedge one writer permanently, so that it always returned SQLITE_BUSY 😱

Copy link
Contributor Author

@bendk bendk May 16, 2024

Choose a reason for hiding this comment

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

Seems good for now, I updated the PR to do that.

Long-term, I still kind of like separating the connections since it allows you to cancel each separately. The current interrupt_ingestion method could also interrupt a call to dismiss_suggestion. I think there's a way to do it safely, although maybe it's just because I haven't been burned by SQLite yet.

(https://bugzilla.mozilla.org/show_bug.cgi?id=1897299)

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, @bendk, and I'm truly sorry if my reaction came off as short in any way—I was running a little late for an appointment earlier, and you deserved a more thoughtful response with more time. I left some more noodlings on https://bugzilla.mozilla.org/show_bug.cgi?id=1897299 for your consideration 🧠

@codecov-commenter
Copy link

codecov-commenter commented May 16, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 50.85%. Comparing base (1ebbd1a) to head (767350e).

Additional details and impacted files
@@             Coverage Diff             @@
##             main    #6246       +/-   ##
===========================================
- Coverage   83.68%   50.85%   -32.84%     
===========================================
  Files         117      112        -5     
  Lines       15653    11811     -3842     
===========================================
- Hits        13099     6006     -7093     
- Misses       2554     5805     +3251     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@linabutler linabutler left a comment

Choose a reason for hiding this comment

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

The shape of the API looks great (thanks for doing this!), but having a second writer is inviting dragons 🐉

Would you mind dropping that in favor of having interrupt_ingestion() just interrupt the existing writer?

@bendk bendk force-pushed the suggest-ingestion-interrupt branch 2 times, most recently from 401dd7f to 319bc7f Compare May 16, 2024 20:42
@@ -651,10 +659,11 @@ impl<'a> SuggestDao<'a> {
&mut self,
record_id: &SuggestRecordId,
suggestions: &[DownloadedAmoSuggestion],
ingest_interrupt_scope: &SqlInterruptScope,
Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh, I had SuggestDao hold an interrupt scope specifically so that we could avoid passing it around 😄

The Dao is a transient object that only lives for the lifetime of a read() or write() call, so I was thinking that, if you wanted a separate interrupt scope for just ingestion, you could create a SuggestDao with a separate interrupt scope, and that SuggestDao would only live for the lifetime of the ingestion.

WDYT? This isn't blocking by any means; I just wanted to make sure I understood if there were other reasons for passing the scope around explicitly.

Copy link
Contributor Author

@bendk bendk May 17, 2024

Choose a reason for hiding this comment

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

The transaction gets committed at end of write and I didn't want to change that behavior. But it does seem better to just pass around the SuggestDao. I'll update the PR to create a single DAO for the entire ingestion and add a SuggestDao::commit method that we can call. This seems better all-around, I prefer seeing explicit commits in the code.

Copy link
Contributor

@linabutler linabutler left a comment

Choose a reason for hiding this comment

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

Just a comment about passing the interrupt scope around explicitly now, but no need to block on that. Thanks again, @bendk!

@bendk bendk force-pushed the suggest-ingestion-interrupt branch from 319bc7f to 863f41d Compare May 17, 2024 15:38
@bendk
Copy link
Contributor Author

bendk commented May 17, 2024

Updated the change so that instead of creating a new scope at the top of ingest, we create the SuggestDao and re-use it for the entire ingestion. This feels a lot nicer to me, although there's a minor difference because before we would commit the transaction after each individual write call. I don't think this is a big deal for now, we're not getting many reports of failures to ingest.

I'm thinking we can merge this, which will unblock Lina to fix things on iOS, then create a follow-up PR that adds back some extra commits. I also think we could further simplify some code now that we only have one SuggestDao.

@bendk bendk force-pushed the suggest-ingestion-interrupt branch 4 times, most recently from a1ab648 to 2358b87 Compare May 17, 2024 16:44
@bendk
Copy link
Contributor Author

bendk commented May 17, 2024

Pushing one more change that adds back the transaction support here. I did this because a) I realized it wasn't that hard to add it back and b) the code is not quite ready for the other cleanups I wanted to do. Also, I renamed the method back to interrupt_everything since that's the most accurate. Maybe we can add an interrupt_ingestion later on after we discuss it more.

Sorry for moving the target with this one, but I think it's ready for review again now.

Copy link
Contributor

@linabutler linabutler left a comment

Choose a reason for hiding this comment

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

Still LGTM, thanks!

/// if [Self::interrupt_handle::interrupt] is called after the operation starts. Calling
/// [Self::write] multiple times during the operation risks missing a call that happens after
/// between those calls.
pub fn write_scope(&self) -> Result<WriteScope> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Oooo, I really like this!

Copy link
Member

@ncloudioj ncloudioj left a comment

Choose a reason for hiding this comment

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

LGTM, could you also update the README.md to reflect the change? It only covers how to use interrupt() for query().

@ncloudioj
Copy link
Member

Also, I renamed the method back to interrupt_everything since that's the most accurate. Maybe we can add an interrupt_ingestion later on after we discuss it more.

I was gonna ask if it makes sense to consolidate those interrupt calls as consumers almost certainly need to come here to check the document to tell which one should be used. Would interrupt(scope: InterruptScope) sounds better? Where InterruptScope can be read, write, and read-write.

@bendk bendk force-pushed the suggest-ingestion-interrupt branch from 2358b87 to 50a6710 Compare May 17, 2024 21:02
@bendk
Copy link
Contributor Author

bendk commented May 17, 2024

I was gonna ask if it makes sense to consolidate those interrupt calls as consumers almost certainly need to come here to check the document to tell which one should be used. Would interrupt(scope: InterruptScope) sounds better? Where InterruptScope can be read, write, and read-write.

I like this idea, but I feel like "scope" is already somewhat overloaded so I called it InterruptKind. For backwards compatibility, I made this param optional. Hopefully we can update consumers to pass it in and drop the optional part.

@bendk bendk force-pushed the suggest-ingestion-interrupt branch from 50a6710 to e358269 Compare May 17, 2024 21:08
enum InterruptKind {
"Read",
"Write",
"Everything",
Copy link
Contributor

Choose a reason for hiding this comment

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

Absolute nitpick: What do you think of ReadWrite instead of Everything as a name? 😅

This new API is so elegant!

Added an `interrupt_everything` method that interrupts both the read and
write connection.  This is intended for iOS to use to interrupt the
suggest component during shutdown.  See
https://bugzilla.mozilla.org/show_bug.cgi?id=1897299 for a discussion on
next steps here.

Created a new `WriteScope` type that stores an interrupt scope that can
be used for multiple `write` calls.  This allows the ingestion code to
catch all interruptions that happened after the ingestion started. With
the old system, if `interrupt_everything` was called in-between
ingestion two types then we might miss it.
@bendk bendk force-pushed the suggest-ingestion-interrupt branch from e358269 to 767350e Compare May 20, 2024 14:46
@bendk bendk added this pull request to the merge queue May 20, 2024
Merged via the queue into mozilla:main with commit 8bd7ba4 May 20, 2024
15 of 16 checks passed
@bendk bendk deleted the suggest-ingestion-interrupt branch May 20, 2024 17:31
@linabutler
Copy link
Contributor

@Mergifyio backport release-v127

Copy link
Contributor

mergify bot commented May 29, 2024

backport release-v127

✅ Backports have been created

pascalchevrel added a commit that referenced this pull request May 29, 2024
Bug 1897264 - interruption support for ingestion (backport #6246)
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.

None yet

4 participants