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

Outgoing Request Hooks, swapping persistence layers #61

Merged
merged 4 commits into from
Apr 8, 2020

Conversation

hannahhoward
Copy link
Collaborator

Goals

Background on the needs here:

  • There's a strong need in the filecoin ecosystem to be able to swap out blockstores for certain types of requests
  • One of the key paths to optimizing graphsync performance is to be able to use special ipld node types (code-gen'd) for specific use cases

Implementation

This builds on the previous addition of swapping the loader and node-builder-chooser on the response side with similar hooks on the request side. Because the request side has to deal with storing as well as loading, and in order to not end up with duplicate store operations, I've decided to uniquely identify loader/storer combos as alternate persistence options, distinguished by a unique string name. (toyed with trying to not require the string name, but as you know, go is not good with comparability in function types)

Implementation:

  • Test Infra: Add a codegen'd node type for the existing test blockchain
  • Add function to registering persistence options by name + loader/storer combo
  • Add concept of outgoing request hook -- unlike the incoming hook (on the response manager), this hook modifies how outgoing requests from the request manager get processed
  • Rename hooks to achieve name symmetry (only production use right now is FC, so we can handle updates)
  • Add alternate queues to the async loading system -- split processing of responses by the persistence option they use
  • Add request hooks to the request manager for outgoing request hooks
  • Refactor the async loader tests significantly for conciseness and clarify, more DRY
  • Refactor response manager hooks to use named persistence options rather than loader directly
  • Build test chain using custom node types and add the ability to check that correct node types were used in traverse
  • Add integration test to demonstrate round trip functionality -- loader and storing from an alternate store and using a custom node type.

rename hooks, add outgoing request hook, define chain types for node builder chooser tests
add persistence options to asyncloader & responsemanager + handling
Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

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

basic post-merge review. LGTM but I'm missing the context I'd need to be sure.

for _, requestHook := range rm.requestHooks {
requestHook.hook(p, request, ha)
if ha.err != nil {
rm.requestHooksLk.RUnlock()
rm.persistenceOptionsLk.RUnlock()
Copy link
Member

Choose a reason for hiding this comment

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

uber-nit: I'd be consistent in the order in which we release these locks (not necessary at all, just slightly nicer).

response := make(chan error, 1)
select {
case <-al.ctx.Done():
return errors.New("context closed")
Copy link
Member

Choose a reason for hiding this comment

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

nit: "async loader closed". ditto below

err := rpom.register(al)
select {
case <-al.ctx.Done():
case rpom.response <- err:
Copy link
Member

Choose a reason for hiding this comment

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

isn't this channel guaranteed to be buffered?

case al.incomingMessages <- &startRequestMessage{requestID}:
return errors.New("context closed")
case err := <-response:
return err
Copy link
Member

Choose a reason for hiding this comment

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

may be simpler to just guarantee that we process all inbound requests. incomingMessages isn't buffered anyways so we can guarantee that we send back a response for all incoming messages we receive.

// fall back to local store
stream, loadErr := loader(link, ipld.LinkContext{})
if stream != nil && loadErr == nil {
localData, loadErr := ioutil.ReadAll(stream)
Copy link
Member

Choose a reason for hiding this comment

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

This is safe as long as we're sure we trust the local store. Probably fine, just calling this out to make sure.

@aschmahmann aschmahmann mentioned this pull request Sep 22, 2020
72 tasks
marten-seemann pushed a commit that referenced this pull request Mar 2, 2023
* build(scripts): add imports + release scripts

* style(imports): fix import style

use standard import style via script

* ci(circle): add imports-check, cbor-gen-check

* docs(CHANGELOG): add changelog with releases record
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.

2 participants