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

Introduce cache and more pagination. #180

Merged
merged 13 commits into from
Apr 16, 2020
Merged

Conversation

jholdstock
Copy link
Member

As discussed on Matrix, bundling changes from #173 and #174 into a new PR with some additional changes.

New style errors

This PR implements the new error modals as defined by @MariaPleshkova in https://xd.adobe.com/view/a814493c-193a-4dfc-5735-0e6d459a6924-de25/. These errors are displayed when an invalid URL is visited, for example /account?address=NotARealAddress. When you are searching for an account using the AJAX form, the errors should be displayed as before, this PR does not change those.

Note: This PR does not change the Javascript warning - that will need some extra thought because it cannot be implemented as a modal - drawing a modal depends on Javascript.

Cache

Cache has been introduced, which acts as a data buffer between hub and gui. Cache has setter functions which are used by the hub, and getter functions which are used by gui. It holds pre-formatted data which is ready to be served directly to gui without needing to lock any mutexes in the hub or hit the database. This facilitates implementing #167 because now the hub is able to push data into the cache when it knows the data has changed, whereas the previous model had the gui pulling data from the hub on a timer, with no knowledge of whether the underlying data had changed or not.

Pagination

Pagination has been added for both the Mined Blocks and the Connected Clients tables on the account page.

Rate Limiting

Rate limiting moved to a middleware which removes a lot of duplicated code.

As a result, rate limiting has been added to some places it was previously missing:

  • /ws the websocket route
  • /logout for admin logout

The limit has been increased from 3 to 5 for GUI clients. This is because some of the pages are now making extra requests (pagination, establishing a websocket, AJAX form submissions) and the limit of 3 was causing issues.

gui/gui.go Outdated

guiRouter.HandleFunc("/", ui.Homepage).Methods("GET")
guiRouter.HandleFunc("/account", ui.Account).Methods("GET")
guiRouter.HandleFunc("/account_exist", ui.IsPoolAccount).Methods("GET")
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps this route could be /account/exist, /poolaccount, /isaccount or /exist? These options conform to the route definitions structure already in place, account_exist, with that underscore does not.

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 catch. Reading further on this topic I believe a more proper solution would be to use the same /account URL as the page itself, but change the request type to HEAD.

https://stackoverflow.com/questions/21087913/proper-route-for-checking-resource-existence-in-a-restful-api
also links through to https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html (section 9.4 is useful)

gui/gui.go Outdated
ui.poolHash = hashString(poolHash)
ui.poolHashMtx.Unlock()
return nil
// Initalise the cache
Copy link
Member

Choose a reason for hiding this comment

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

Missing comment punctuation.

pool/hub.go Outdated
// FetchClientInfo returns connection details about all pool clients.
func (h *Hub) FetchClientInfo() map[string][]*ClientInfo {
clientInfo := make(map[string][]*ClientInfo)
func (h *Hub) FetchClientInfo() []*Client {
Copy link
Member

Choose a reason for hiding this comment

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

If you're going to maintain the modifications to this function then the function signature will have to change some more. Since it's returning a slice of clients now I don't think it should be called FetchClientInfo anymore, perhaps FetchHubClients or FetchClients would do. Also the name allClients seems unnecessary here, you could call the client slice clients and enumerate the endpoint with for _, c := range endpoint.clients, this way you can append to the slice like this: clients = append(clients, c). I think this is readable without being verbose.

@@ -93,27 +93,14 @@ func testAcceptedWork(t *testing.T, db *bolt.DB) {
fetchedWork.Height, workC.Height)
}

// Ensure requesting negative or zero most recent accepted work returns
// an error.
_, err = listMinedWorkByAccount(db, string(id), -1)
Copy link
Member

Choose a reason for hiding this comment

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

Can we keep listMinedWorkByAccount around just for these tests?

Copy link
Member Author

Choose a reason for hiding this comment

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

listMinedWorkByAccount was called three times in test code.

Two of these appearances were just testing the behaviour of listMinedWorkByAccount itself, so I wont bother to reinstate those.

The third call was to ensure mined work is persisted in the database correctly, so this one seems worth reinstating. I will put back some code which performs this check.

Copy link
Member

@dnldd dnldd left a comment

Choose a reason for hiding this comment

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

Not done with my review, I have a couple more diffs to get through. Will update when I'm done. Regarding the cache update I think It's on the right path, we can pass a channel to the gui to read for cache update signals and process them accordingly.

gui/gui.go Outdated
// FetchClientInfo returns connection details about all pool clients.
FetchClientInfo func() map[string][]*pool.ClientInfo
// FetchClientInfo returns details about all connected pool clients.
FetchClientInfo func() []*pool.Client
Copy link
Member

Choose a reason for hiding this comment

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

This would have to be updated as well as the description if you make the changes suggested to the function signature.

gui/cache.go Outdated
poolHashMtx sync.RWMutex

clients map[string][]client
clientsMtx sync.RWMutex
Copy link
Member

@dnldd dnldd Apr 13, 2020

Choose a reason for hiding this comment

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

Don't think it's necessary to group struct fields like this, I think the codebase only has atomically updated fields separated from the rest.

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean the new lines? I included those just for the sake of readability and making it easier to see that each field has its own mutex, but I am happy to remove them.

@dnldd
Copy link
Member

dnldd commented Apr 13, 2020

Done reviewing.

@jholdstock
Copy link
Member Author

Thanks @dnldd, I've pushed commits implementing review changes.

pool/hub.go Outdated
// FetchClientInfo returns connection details about all pool clients.
func (h *Hub) FetchClientInfo() []*Client {
allClients := make([]*Client, 0)
// FetchClients returns connection details about all pool clients.
Copy link
Member

Choose a reason for hiding this comment

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

// FetchClients returns all connected pool clients.

gui/gui.go Outdated
@@ -76,8 +76,8 @@ type Config struct {
FetchWorkQuotas func() ([]*pool.Quota, error)
// BackupDB streams a backup of the database over an http response.
BackupDB func(w http.ResponseWriter) error
// FetchClientInfo returns details about all connected pool clients.
FetchClientInfo func() []*pool.Client
// FetchClients returns details about all connected pool clients.
Copy link
Member

Choose a reason for hiding this comment

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

// FetchClients returns all connected pool clients.

@dnldd
Copy link
Member

dnldd commented Apr 16, 2020

Minor comment updates and we're good to go @jholdstock

@jholdstock
Copy link
Member Author

Done

@jholdstock jholdstock merged commit 167fa18 into decred:master Apr 16, 2020
@jholdstock jholdstock deleted the pagination6 branch October 6, 2020 09:22
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

2 participants