Removes duplicated logic in server module#443
Conversation
|
Drone is failing because a transient failure. If you're not allowed to restart a job, I think you should ask @src-d/infrastructure creating an issue into infrastructure repo |
|
|
||
| type sleepyErrAnalyzer struct{} | ||
|
|
||
| func (a *sleepyErrAnalyzer) NotifyReviewEvent(ctx context.Context, e *lookout.ReviewEvent) (*lookout.EventResponse, error) { |
There was a problem hiding this comment.
line is 124 characters (lll)
If you have feedback about this comment, please, tell us.
| suite.sendEvent(successJSON) | ||
|
|
||
| suite.GrepTrue(suite.r, `msg="analysis failed" analyzer=Dummy app=lookoutd error="rpc error: code = Unknown desc = review error"`) | ||
| suite.GrepTrue(suite.r, `msg="analysis failed: code: Unknown - message: review error" analyzer=Dummy app=lookoutd error="rpc error: code = Unknown desc = review error"`) |
There was a problem hiding this comment.
line is 170 characters (lll)
If you have feedback about this comment, please, tell us.
| suite.Run(t, &ErrorAnalyzerIntegrationSuite{ | ||
| configFile: dummyConfigFile, | ||
| analyzer: &errAnalyzer{}, | ||
| errMessage: `msg="analysis failed: code: Unknown - message: review error" analyzer=Dummy app=lookoutd error="rpc error: code = Unknown desc = review error"`, |
There was a problem hiding this comment.
line is 159 characters (lll)
If you have feedback about this comment, please, tell us.
| suite.Run(t, &ErrorAnalyzerIntegrationSuite{ | ||
| configFile: dummyConfigFileWithTimeouts, | ||
| analyzer: &sleepyErrAnalyzer{}, | ||
| errMessage: `msg="analysis failed: timeout exceeded, try increasing analyzerReviewTimeout" analyzer=Dummy app=lookoutd error="rpc error: code = DeadlineExceeded desc = context deadline exceeded"`, |
There was a problem hiding this comment.
line is 198 characters (lll)
If you have feedback about this comment, please, tell us.
| getAnalyzerNotifier := func(ctx context.Context, settings map[string]interface{}) (analyzerNotifier, error) { | ||
| st := grpchelper.ToPBStruct(settings) | ||
| switch ev := e.(type) { | ||
| case *lookout.ReviewEvent: |
There was a problem hiding this comment.
duplicate of server/server.go:172-179 (dupl)
If you have feedback about this comment, please, tell us.
| func(ctx context.Context, a lookout.AnalyzerClient) (*pb.EventResponse, error) { | ||
| return a.NotifyReviewEvent(ctx, ev) | ||
| }, s.analyzerReviewTimeout}, nil | ||
| case *lookout.PushEvent: |
There was a problem hiding this comment.
duplicate of server/server.go:164-171 (dupl)
If you have feedback about this comment, please, tell us.
| } | ||
|
|
||
| func (s *Server) concurrentRequest(ctx context.Context, conf map[string]lookout.AnalyzerConfig, send reqSent) ([]lookout.AnalyzerComments, error) { | ||
| func (s *Server) concurrentRequest(ctx context.Context, conf map[string]lookout.AnalyzerConfig, send reqSent, logErrorMessages map[codes.Code]string) ([]lookout.AnalyzerComments, error) { |
There was a problem hiding this comment.
line is 187 characters (lll)
If you have feedback about this comment, please, tell us.
77b37fc to
1326678
Compare
dpordomingo
left a comment
There was a problem hiding this comment.
Thanks for caring!
I think it's a good idea caring about removing duplicate code, but there are some suggestions that I'd like to do.
There is also a personal concern about changing the behavior of Server.HandleReview(Context, *ReviewEvent, bool) error when processing unsuported Events.
I also wonder if the initial implementation was coded that way (with that dupe code) considering any planned change, that might cause that both event handlers were totally different.
| ev.Configuration = *st | ||
| } | ||
| return analyzerNotifier{ | ||
| func(ctx context.Context, a lookout.AnalyzerClient) (*pb.EventResponse, error) { |
There was a problem hiding this comment.
We try to avoid structs initialized with positional arguments because they're harder to read and can cause problems in some cases (like changing the order of properties having the same type, or adding new properties).
imho I'd prefer:
return analyzerNotifier{
notify: func...
timeot: s.analyzerReviewTimeout
}, nil| return a.NotifyPushEvent(ctx, ev) | ||
| }, s.analyzerPushTimeout}, nil | ||
| default: | ||
| ctxlog.Get(ctx).Debugf("ignoring unsupported event: %s", ev) |
There was a problem hiding this comment.
I think we're moving the logic to validate the event too deep
s.HandleEvent(ctx, strangeEvent) ->
s.AnalyzeAndComment(ctx, strangeEvent, isSafePosting) ->
s.analyze(ctx, strangeEvent, isSafePosting) ->
s.getSender(strangeEvent) ->
getAnalyzerNotifier(ctx, errorMsgMap) ->
if unsupported return fmt.Errorf("unsupported")instead of how we did initially:
s.HandleEvent(ctx, strangeEvent) ->
if unsupported fmt.Debug("unsupported")I do not see the benefit of moving that validation so deep.
There was a problem hiding this comment.
That's another point against the refactor. The reason for this was to avoid checking twice the type of the event using the switch.
| }, s.analyzerPushTimeout}, nil | ||
| default: | ||
| ctxlog.Get(ctx).Debugf("ignoring unsupported event: %s", ev) | ||
| return analyzerNotifier{}, fmt.Errorf("unsupported event: %s", ev) |
There was a problem hiding this comment.
I might be mistaken, but this PR is also changing the s.HandleEvent(ctx, strangeEvent) behavior when it is sent an event that was not a ReviewEvent nor a PushEvent;
If I'm rightm the s.HandleEvent(ctx, strangeEvent) will fail with an unsupported error message, instead of just logging a debug unsupported message.
If that's true, I think we should not change the behavior in a refactor PR or without a clear reasons to do so.
There was a problem hiding this comment.
You're right. With these changes the HandleEvent method fails in case on supported event. Another thing to note with this refactor is that in case of unsupported event the check is so deep that it even spawns a goroutine for each analyzer. And this is a big no-no in my opionion.
| } | ||
|
|
||
| func (s *Server) analyze(ctx context.Context, e lookout.Event, safePosting bool) ([]lookout.AnalyzerComments, error) { | ||
| ctxlog.Get(ctx).Infof("processing event type %d", e.Type()) |
There was a problem hiding this comment.
I see more cryptic the new error message: event type 2 instead of pull request
There was a problem hiding this comment.
Agree on this too, in fact an idea could be to add a stringer to EventType in lookout-sdk.
There was a problem hiding this comment.
In other place we are doing reflect.TypeOf(e).String()
| } | ||
|
|
||
| func (s *Server) analyze(ctx context.Context, e lookout.Event, safePosting bool) ([]lookout.AnalyzerComments, error) { | ||
| ctxlog.Get(ctx).Infof("processing event type %d", e.Type()) |
There was a problem hiding this comment.
I think we're also missing info about the event provider (see 1326678#diff-91bbeda7eb98a7adc57b9e47e2cf5c2bL188)
There was a problem hiding this comment.
You're right, I forgot to add it in to the log ctx.
| if err == nil { | ||
| if err := s.post(ctx, e, comments, safePosting); err != nil { | ||
| s.status(ctx, e, lookout.ErrorAnalysisStatus) | ||
| err = fmt.Errorf("posting analysis failed: %s", err) |
There was a problem hiding this comment.
This assignment does not apply over first err definition #line-124, but over its own scope #line-126
We avoid it, doing early returns; it means, that we stop processing as soon as an error condition is met; example:
if err := doSomething(); err != nil {
return fmt.Errorf("new deep error") // we stop processing
}
// do other thingsinstead of moving errors and reusing variables containing it, like in your example:
var err error
if err := doSomething(); err != nil { // we shadow the upper err definition
err = fmt.Errorf("new deep error") // this definition does not apply over the upper scope
}
return err // nothing was overriden; we got <nil>You can see an example about it at: https://play.golang.org/p/I75A6xUtJgN
| s.status(ctx, e, lookout.SuccessAnalysisStatus) | ||
| } | ||
| } | ||
| return err |
There was a problem hiding this comment.
we always introduce a new line after every code block
| var comments []lookout.AnalyzerComments | ||
| if err := e.Validate(); err != nil { | ||
| return err | ||
| return comments, err |
There was a problem hiding this comment.
we use to avoid indirections when doing an early return caused by an error; example:
func doSomething() (string, error) {
var msg string
// do things, operate with msg...
// at some point, we check an error, and we do:
if err := checkSomething(); err != nil {
return "", err // instead of `return msg, err`; relying on a previous value of `msg`
}
}That way, we do explicit the things that we return
| conf, err := s.getConfig(ctx, e) | ||
| if err != nil { | ||
| return err | ||
| return comments, err |
| var comments []*lookout.Comment | ||
| analyzerNotifier, err := getAnalyzerNotifier(ctx, settings) | ||
| if err != nil { | ||
| return comments, err |
There was a problem hiding this comment.
idem. about returning errors.
|
I saw some messages from
|
Exactly, I was thinking the same thing that I could have been missing the big picture and future planned change. |
|
Overall it seems that the are some possible performance issues by eye. And even if it removes some dup code, it may trade-off the linearity of the steps too much. |
Signed-off-by: Lou Marvin Caraig <loumarvincaraig@gmail.com>
Signed-off-by: Lou Marvin Caraig <loumarvincaraig@gmail.com>
Signed-off-by: Lou Marvin Caraig <loumarvincaraig@gmail.com>
Signed-off-by: Lou Marvin Caraig <loumarvincaraig@gmail.com>
1326678 to
d76d5b5
Compare
| suite.sendEvent(successJSON) | ||
| suite.GrepAll(suite.r, []string{ | ||
| `processing pull request`, | ||
| `processing event type 2`, |
There was a problem hiding this comment.
hm. The previous message was much better.
|
Usually, it's a good idea to remove duplicated code, but I see 2 problems with this PR:
Though I agree a current code of this module needs some improvements. |
|
I'm gonna close this PR ;) |

This depends on #442. Please see here.