Skip to content
This repository has been archived by the owner on Oct 23, 2022. It is now read-only.

Adds basic support for pin and unpin operations #117

Merged
merged 15 commits into from
Mar 27, 2020

Conversation

saresend
Copy link
Contributor

@saresend saresend commented Mar 23, 2020

What

Should address #11, by adding some basic pin / unpin operations to the dag

Todo

  • Add support for querying whether a block is pinned
  • Add Tests once design is finished

@saresend saresend mentioned this pull request Mar 23, 2020
@aphelionz
Copy link
Contributor

This is really exciting, thank you @saresend. If this works for @koivunej then it'd be great to see tests, and then if you want to go for the gold, add the http endpoints! 🎉

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 23, 2020

I guess remove should check if the block is pinned.

@saresend
Copy link
Contributor Author

Alright, a couple of changes:

  • First, pinning is defined by the existence of a pair in the Pin hashmap, rather than a boolean flag of 1 or 0. This way we don't have two False states, in the form of Null or Zero, and instead consolidate all into the null case.

  • It should now also error when trying to unpin an unpinned block, rather than just silently performing a no-op.

@aphelionz
Copy link
Contributor

aphelionz commented Mar 24, 2020

@saresend Here's the overall spec, including what the conformance tests expect for the /pin APIs. I hope this is helpful. Let me know if you have any questions

rs-ipfs/ipfs-rust-conformance#2

Edit: /pin APIs

Copy link
Contributor

@dvc94ch dvc94ch left a comment

Choose a reason for hiding this comment

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

I assume you're done with this? Could you please rebase your branch?

@saresend
Copy link
Contributor Author

I was going to add some tests at the very least. I might leave the actual http endpoints to a separate PR however. If you have some code points for how you write tests for this project, I'd be happy to add them.

@aphelionz
Copy link
Contributor

@saresend @dvc94ch Tests and doc would be important. You can add simple module tests at the end of the respective files, e.g. dag.rs and repo/mod.rs. It would also be huge if you could do the endpoints. There's more examples of testing in that crate as well.

Thank you so much again for this.

@saresend
Copy link
Contributor Author

No problem, I'll open up a new PR for the http endpoints, just to keep concerns separate!

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

It's also not clear why you're exposing it on the dag, why unpin should error if a block already is unpinned, as stuff may share blocks or how this works as you can still remove a block even if it's pinned.

@saresend
Copy link
Contributor Author

Totally fair, I'm still ramping up on IPFS and don't have great context on how you envision this being architected or how concerns are being separated. If you have suggestions on better ways to expose the API I'm all ears. My understanding of pinning is that it protects against garbage collection, and I wasn't able to find whether garbage collection is already being done in rust-ipfs. My thought was that garbage collection could leverage the pinning query logic when removing nodes whenever it does get built

@aphelionz
Copy link
Contributor

As far as the error goes, it should simply follow what js-ipfs or go-ipfs does. So if they error when trying to unpin and already unpinned block, then we should too. Otherwise not.

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

I don't think the dag should expose pin/unpin, and if it did then the semantics would probably not be to pin the root of a path as a path can point to other blocks, so you'd want to pin the last block it refers to.

Yes pin is for garbage collection, which is not currently implemented. What currently is implemented is manually removing blocks, which shouldn't happen if it's pinned.

Since blocks can be shared, pinning should probably increment a counter and unpin should decrement it, instead of having a boolean.

Garbage collection can be implemented by iterating through all blocks, checking if the pin count is zero and if it is remove the block.

@saresend
Copy link
Contributor Author

Where would you recommend pinning be implemented?

src/lib.rs Outdated
@@ -312,6 +312,21 @@ impl<Types: IpfsTypes> Ipfs<Types> {
Ok(self.repo.remove_block(cid).await?)
}

/// Pins a given Cid
pub async fn pin_block(&self, path: IpfsPath) -> Result<(), Error> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub async fn pin_block(&self, path: IpfsPath) -> Result<(), Error> {
pub async fn pin_block(&self, cid: &Cid) -> Result<(), Error> {
self.repo.pin_block(cid).await
}

@aphelionz
Copy link
Contributor

I might suggest we focus on tests and the HTTP endpoints here, so that at least there's a foundation for architecture changes + refactors. Always room for improvement, especially if we keep getting awesome community contributions.

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

Do you have anything to add in regards to my comment? Did I not explain in which ways the implementation suggested here is flawed clearly enough? Conformance tests are not a way to avoid using your brain, as tests are just as buggy as code. Besides tests do not ensure correctness, they sometimes show the presence of bugs.

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

Let me try again, I'll use letters to denote blocks in the following diagram:

a -> b <- c

and these two concurrent processes running in parallel

process 1:
    put(b)
    pin(b)
    put(a)
    pin(a)
    ...
    unpin(a)
    unpin(b)
    gc()
process 2:
    put(b)
    pin(b)
    put(c)
    pin(c)

    get(b)???

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

Also put should probably pin automatically to prevent a race, but that's something to be discussed, if someone can supply a usecase where you don't want to put_and_pin

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 25, 2020

I approved the PR and would have merged it if it didn't have conflicts with master. But I agree with @aphelionz, this features flaws should be extensively documented and tested.

@saresend
Copy link
Contributor Author

Before the next couple changes, I just want to clarify what you'd want for this PR. So far, the changes requested are:

  • Move to use &Cid, rather than ipfsPath
  • Automatically Pin on Put actions
  • Prevent removal based on whether a block is pinned
  • Add tests and documentation

Is there anything I'm missing here?

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 26, 2020

If we didn't have the conformance tests I'd suggest removing remove altogether. Also don't use a bool as shown in the example above it can lead to issues. But mainly I'm a bit annoyed, which has nothing to do with your pr. Thanks for contributing...

@saresend
Copy link
Contributor Author

@dvc94ch @aphelionz, alright this should include a more RC like logic for pinning, removes it from the Dag API, and finally includes a test to verify behavior. It should also now be rebased so if it all checks out feel free to merge.

@dvc94ch
Copy link
Contributor

dvc94ch commented Mar 27, 2020

Looks good! So I think this is much better, thanks. Can you rebase again, looks like it's not mergeable.

@saresend
Copy link
Contributor Author

Alright that should be merged!

@koivunej
Copy link
Collaborator

Interesting the same test is flaky on windows ... Again. Need to investigate why.

Copy link
Collaborator

@koivunej koivunej left a comment

Choose a reason for hiding this comment

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

Looks good!

@koivunej
Copy link
Collaborator

The test failure will be fixed with #124 but I think this is now good to merge?

@koivunej koivunej merged commit 0d214dc into rs-ipfs:master Mar 27, 2020
@aphelionz
Copy link
Contributor

@saresend Please add yourself to rs-ipfs/welcome#1 and also let us know if you plan on doing the endpoints as well

@saresend
Copy link
Contributor Author

saresend commented Apr 1, 2020

Yep! I plan to have a PR up in the next week or so, classes have started back up again for me so it may take me a bit longer unfortunately

@aphelionz
Copy link
Contributor

That's ok, no rush.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants