-
Notifications
You must be signed in to change notification settings - Fork 1.3k
status-indicator: Display external service validation and syncing errors #4804
Conversation
len(es), strings.Join(points, "\n\t")) | ||
} | ||
|
||
type MultiSourceError struct { |
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 makes this type necessary? Can't we work with multierror.Error
of SourceError
s?
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.
That's what I did first, but it lead to the code looking like this:
if multiErr, ok := err.(*multierror.Error); ok {
for _, sub := range multiErr.Errors {
if sourceErr, ok := sub.(*SourceError); ok {
m := newSyncErrMessage(sourceErr)
resp.Messages = append(resp.Messages, m)
} else {
// drop error? add generic message?
}
}
} else {
// drop error? add generic message?
}
That seems a bit unwieldy and MultiSourceError
was me trying my hand at putting some more information back into the type system. But I'm not set on it.
I think the general problem that needs to be solved is the association of errors to external services and making those accessible to consumers. multierror.Error
and MultiSourceError
are equally capable of doing this, but I feel like there might be an even better approach.
I'm also thinking that maybe we need a map that gets updated with each sync run, kinda like map[*ExternalService]error
. That would then also allow us to show the status per external service when everything went fine. But in order to implement that, we still need to find out what happened with each external service inside the syncer, so at least *SourceError
seems necessary?
And another problem is that, of course, the Err
in *SourceError
is also a multierror.Error
and doesn't lead to the most UI-friendly messages (2 errors occured:\n\t* blub\n\t* blah
...). I thought about using a custom format func for this, but that would only lead to a custom format in repo-updater
that then needs to be untangled in the TypeScript world?
Update after talking this through with @keegancsmith and @tsenart:
I'll be out of the office for the next three days. From my side, it'd totally fine to merge this (again, as long as build passes and your code reviews didn't yield any criticial bugs I've overlooked) and refine it later. But if there are any customer-side concerns, let's refine it in this PR before merging. |
Codecov Report
@@ Coverage Diff @@
## master #4804 +/- ##
==========================================
+ Coverage 48.07% 48.11% +0.04%
==========================================
Files 726 726
Lines 44263 44361 +98
Branches 1761 1761
==========================================
+ Hits 21278 21343 +65
- Misses 21004 21032 +28
- Partials 1981 1986 +5
|
# The name of this metadata pair. | ||
name: String! | ||
# The data of this metadata pair. | ||
value: String! |
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.
So is this type just a way to get an untyped key/value bag? Why can't this metadata be typed?
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.
Because the metadata differs depending on which type the StatusMessage
has. AFAIK GraphQL doesn't support union types, which is what I'd want 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.
GraphQL does support union types
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.
Ah, interesting! 🤔
Regarding the errors:
|
Agree! And that's actually a lot of work, because we'd basically need to map arbitrary errors into actionable items for each code host. And at which layer do we do that? In each code host client? GraphQL layer? Web? I don't know how feasible that is (which is not to say that it isn't). |
Since this is something that is only shown to admin users, I think it is worth experimenting with and getting feedback on. I agree with @felixfbecker that an improved experience would be something more actionable, but I understand that would require specific mapping. What if we just mapped the most common errors (e.g. 401 (bad credentials), 404 (probably bad repo path?), 504 (host unavailable)) so that at least the common cases are a bit more usable, then the rest of them can stay in their raw state, essentially solving for the 80% scenario. Thoughts? |
The more I thought I about it, the more I think this is a requirement before we can ship. I'm closing this PR (since it was a prototype thing anyway) and will re-open later once I have a second iteration done that includes the suggestions made by @tsenart @felixfbecker and @christinaforney. |
I did not look at the code but I do think it would be ok to be incremental about improving our error handling here. My understanding from a conversation with @mrnugget is that it is currently possible for the user to not see a warning when saving an external service (if the sync takes too long), or worse, see a warning caused by an external service other than the one that is currently being saved. This seems like a valuable problem to fix.
All else equal, of course pretty errors are better, but showing not pretty errors is a big improvement over not showing errors at all, so I wouldn't block a change like this on the errors not looking pretty. Supporting more types of errors is also something that can happen as necessary in the future, so I think it is fine to just implement one error to begin with. |
This extends the global status indicator with a new status message:
SYNCERROR
. The message is produced whenever the initial construction of an external service "source" fails (due to invalid tokens, invalid config, etc.) or when syncing the repositories fails.This is one of the "extension" ideas outlined here: https://github.com/sourcegraph/sourcegraph/issues/4120
And it's also better UX now that we've moved the syncing into the background, where errors could possibly disappear: https://github.com/sourcegraph/sourcegraph/issues/4357#issuecomment-499060771
Screenshot of current state:
It works as intended, but I'd love to get more feedback on the following:
MultiSourceError
/SourceError
solution). I feel like this could maybe be cleaner.Test plan: manual testing,
go test
,cd web && yarn test --runInBand StatusMessagesNavItem.test.tsx