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

Add results receiving API to Go webapp #142

Merged
merged 6 commits into from
May 15, 2018
Merged

Conversation

Hexcles
Copy link
Member

@Hexcles Hexcles commented May 11, 2018

This is the receiver part of the results receiver API (sorry for the confusing name), which is implemented inside the default Go app.

This PR implements almost everything in the design doc -- except the authentication of the uploaders, which will be added in a follow-up PR.

Tracking issue: #55

@Hexcles Hexcles requested a review from lukebjerring May 11, 2018 20:13
@Hexcles
Copy link
Member Author

Hexcles commented May 11, 2018

Manual staging deployment: https://robertma-dev-dot-wptdashboard.appspot.com/api/results/upload

(need to login as admin)

queue:
- name: results-arrival
target: processor
rate: 1/m
Copy link
Contributor

Choose a reason for hiding this comment

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

Why 1 per min? Is there an impact of having it more often / less often?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, I didn't mean to set the rate. It's the max_concurrent_requests that I wanted to change because I use manual scaling for the Flex service.

Removed rate and added max_concurrent_requests (set to 1 for now).

req := httptest.NewRequest("GET", "/api/results/upload", new(strings.Reader))
resp := httptest.NewRecorder()
mockAE := NewMockAppEngineAPI(mockCtrl)
mockAE.EXPECT().login("/api/results/upload").Return(false, "http://wpt.fyi/login")
Copy link
Contributor

Choose a reason for hiding this comment

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

"/login" would be more environment-independent.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

<label> result_url <input name="result_url"></label><br>
<input type="submit">
</form>
</html>`
Copy link
Contributor

Choose a reason for hiding this comment

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

Put the HTML in a template file (e.g. /templates/admin/upload)

Copy link
Member Author

Choose a reason for hiding this comment

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

@lukebjerring I'm having path issues, different CWD in unit tests vs. prod/dev_appserver. (similar to what you saw when you were playing with browsers.json). How can I work around this?

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussed with @lukebjerring offline. We didn't really find a good solution for the path issue per se, but we decided to move this page to webapp.

t, err = handleFilePayload(a, uploader, f)
}
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to return after erroring.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
fmt.Printf("Task %s added to queue\n", t.Name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Write this to the response?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

return w, nil
}

var _ gcs = (*gcsImpl)(nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

assert.Nil(t, err)

assert.Equal(t, path, fmt.Sprintf("/%s/test.json", BufferBucket))
assert.Equal(t, bytes.Compare(mGcs.mockWriter.finalContent, []byte("test content")), 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think assert.Equal(t, string(mGcs.mockWriter.finalContent), "test content") will give you a more readable output if a regression occurs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

}
}

func (a *appEngineAPIImpl) login(url string) (loggedIn bool, loginURL string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this API strange, because it doesn't actually log anyone in (even via side-effects of user.Current).

Maybe have 2 methods, isLoggedIn, and getLoginUrl(redirect string) ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point! Done.

isAdmin() bool
login(url string) (loggedIn bool, loginURL string)
uploadToGCS(fileName string, f io.Reader, gzipped bool) (gcsPath string, err error)
scheduleResultsTask(uploader string, gcsPaths []string, payloadType string) (*taskqueue.Task, error)
Copy link
Contributor

Choose a reason for hiding this comment

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

taskqueue.Task is a struct, not an interface. Should it be abstracted for testing?

Copy link
Member Author

Choose a reason for hiding this comment

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

AFAIK it doesn't have any exported methods. And all we need are its exported fields. I don't think we can abstract fields using interface, can we?

There are two reasons:

1. Referencing to webapp/templates from other packages (directories) is
   no fun because of the changing CWD during unit testing.
2. Since the admin upload page isn't really an API, it makes more
   logical sense to put it in webapp.
@Hexcles
Copy link
Member Author

Hexcles commented May 14, 2018

After discussion the admin-only upload page is now moved to webapp with a new URL: /admin/results/upload. Staging: https://robertma-dev-dot-wptdashboard.appspot.com/admin/results/upload

Rationales:

  1. Referencing to webapp/templates from other packages (directories) is no fun because of the changing CWD during unit testing.
  2. Since the admin upload page isn't really an API, it makes more logical sense to put it in webapp.

@lukebjerring PTAL

@Hexcles Hexcles changed the title Results receiver Add results receiving API to Go webapp May 14, 2018
@lukebjerring lukebjerring merged commit 591352e into master May 15, 2018
@lukebjerring lukebjerring deleted the results-receiver branch May 15, 2018 19:30
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.

3 participants