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

Rework error handling #3549

Merged
merged 33 commits into from
Dec 19, 2024
Merged

Rework error handling #3549

merged 33 commits into from
Dec 19, 2024

Conversation

finestructure
Copy link
Member

@finestructure finestructure commented Dec 12, 2024

Rationale: https://noteplan.co/n/575ADC0D-8D6C-4ADF-BB25-972717C42C41

To do

This is best reviewed with the "ignore whitespace" setting to hide all the indentation noise from new namespaces.

@cla-bot cla-bot bot added the cla-signed label Dec 12, 2024
/// - database: `Database` object
/// - results: `Joined<Package, Repository>` results to update
/// - stage: Processing stage
func updatePackages(client: Client,
Copy link
Member Author

Choose a reason for hiding this comment

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

updatePackages (note the plural) was only called from analysis. Moving this into the Analyze namespace (which I'll update to Analysis at some point in the future) makes this explicit.

try await recordError(database: database, error: error, stage: stage)
static func updatePackage(client: Client,
database: Database,
result: Result<Joined<Package, Repository>, Error>) async throws {
Copy link
Member Author

Choose a reason for hiding this comment

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

We temporarily introduce specific static updatePackage functions on Analysis (and further down Ingestion) to deal with the fact that Ingestion has transitioned over to a new error type which we're throwing in typed throws while analysis is still using untyped throws and any Error as its error type.

The plan is to consolidate the two again once analysis moves to typed throws as well and base them both on the shared protocol ProcessingError.

.unwrap()
XCTAssertEqual(repo.licenseUrl, "license")
for pkg in try await Package.query(on: app.db).all() {
XCTAssertEqual(pkg.processingStage, .ingestion, "\(pkg.url) must be in ingestion")
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a crucial bit of additional test coverage where we ensure the processing stage is advanced when there are errors.

@@ -354,12 +364,12 @@ class IngestorTests: AppTestCase {

func test_ingest_unique_owner_name_violation() async throws {
// Test error behaviour when two packages resolving to the same owner/name are ingested:
// - don't update package
// - don't create repository records
Copy link
Member Author

Choose a reason for hiding this comment

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

This is an important change to how we're dealing with this error scenario. Previously, we did two things:

  • avoid creating a duplicate repository record
  • avoid updating the related package

We could preserve this behaviour but it actually simplifies things quite a bit to drop the second part of this. And it's the theme of this change: make sure processing is advanced through a stages despite errors.

In order to ensure this change doesn't break things in the following stage, this test now explicitly runs analysis as part of its validation to ensure it doesn't raise any errors (see below).

Comment on lines +443 to +441
try await Analyze.analyze(client: app.client, database: db, mode: .id(.id0))
try await Analyze.analyze(client: app.client, database: db, mode: .id(.id1))
try await XCTAssertEqualAsync(try await Package.find(.id0, on: db)?.processingStage, .analysis)
try await XCTAssertEqualAsync(try await Package.find(.id1, on: db)?.processingStage, .analysis)
Copy link
Member Author

Choose a reason for hiding this comment

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

This is where we're ensuring analysis can deal with this scenario where one package doesn't have a corresponding repository record.

@finestructure
Copy link
Member Author

I'll ad hoc deploy this to dev to let it run over the weekend.

case repositorySaveFailed
case repositorySaveUniqueViolation
}
var shouldFail: @Sendable (_ failureMode: FailureMode) -> Bool = { _ in false }
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've added this error triggering mechanism, which allows us to configure an environment variable FAILURE_MODE as for example

{
    "fetchMetadataFailed": 0.1,
    "findOrCreateRepositoryFailed": 0,
    "invalidURL": 0,
    "noRepositoryMetadata": 0,
    "repositorySaveFailed": 0,
    "repositorySaveUniqueViolation": 0
}

which will trigger a fetchMetadataFailed error at a rate of 10%.

I'm using this to ensure on dev that there's no knock-on effect from errors in subsequent stages. It's also made it easier to ensure locally that the error logs are ok.

We can revert this after testing.

@finestructure
Copy link
Member Author

Ok, this is all working as expected:

Screenshot 2024-12-15 at 13 52 19

@finestructure finestructure marked this pull request as ready for review December 15, 2024 13:52
@finestructure finestructure marked this pull request as draft December 15, 2024 13:53
@finestructure finestructure force-pushed the rework-error-handling branch 4 times, most recently from 6f837a5 to e857fe1 Compare December 18, 2024 06:01
@finestructure
Copy link
Member Author

There's no release of swift-concurrency-extras yet but after switching to track the main branch we got rid of the package name conflict warning at least. We could go ahead and merge this and drop the extra dependency clause once there's been a release in a follow-up.

@finestructure finestructure marked this pull request as ready for review December 18, 2024 06:25
@finestructure
Copy link
Member Author

Now that we've got 1.3.1 of swift-concurrency-extras I've rebased all the package manifest changes out of the PR.

@finestructure finestructure merged commit 8f8c2f0 into main Dec 19, 2024
5 checks passed
@finestructure finestructure deleted the rework-error-handling branch December 19, 2024 08:11
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.

2 participants