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

feat(lock): allow for custom lock options #162

Merged
merged 4 commits into from
Apr 23, 2018
Merged

feat(lock): allow for custom lock options #162

merged 4 commits into from
Apr 23, 2018

Conversation

jacobheun
Copy link
Contributor

@jacobheun jacobheun commented Apr 9, 2018

  • Allows users to create custom repo locks, such as to support the new s3 datastore
  • Allows users to have no repo locking

resolves #161

@daviddias
Copy link
Member

@pgte @dignifiedquire can I get a review from you on this feature?

Copy link
Member

@daviddias daviddias left a comment

Choose a reason for hiding this comment

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

@jacobheun please add docs about this feature


it('allows for no locker', () => {
const repo = new Repo(repoPath, {
locker: false
Copy link
Member

Choose a reason for hiding this comment

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

should also test for undefined options

@@ -25,6 +41,16 @@ describe('IPFS Repo Tests onNode.js', () => {
lock: 'memory'
},
init: true
}, {
name: 'custom locker',
Copy link
Member

Choose a reason for hiding this comment

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

There is no proper locking tests currently, so it would be good to test various locking scenarios in addition to the regular tests

src/index.js Outdated
* @returns {Locker}
*/
_getLocker () {
if (this.options.locker === false) {
Copy link
Member

Choose a reason for hiding this comment

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

This way of options is 👎 from my side. This forces locker to be of multiple types, so disabling the locker should check for != null and be if it is not set, rather than a boolean

Copy link

Choose a reason for hiding this comment

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

I know multiple types for an option isn’t especially desirable, but it feels to me like just using lock for both custom and built-in types instead of adding a new option would be much nicer from the perspective of a user. Maybe we could move towards the type being a Locker object instead of a string? You could support built-ins with:

// Expose the built-in collection as a frozen static var on Repo
new Repo({ lock: Repo.lockers.memory })
// OR
new Repo({ lock: require('ipfs-repo/lock-memory') })

…though we’d probably want to keep string support as a deprecated feature for a little while.

(Found my way here after reviewing ipfs/js-ipfs#1303; I hope I’m not butting in.)

src/index.js Outdated
* @returns {void}
*/
_openLock (path, callback) {
if (this._locker) {
Copy link
Member

Choose a reason for hiding this comment

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

also 👎 on being able to disable the locking, this is just asking for trouble

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am fine with leaving locking required, the custom locker is the needed piece. It's fairly easy to subvert locking at the moment even if we don't explicitly allow it to be disabled. With custom datastore support there is a potential use case for users wanting to handle locking at the object level, rather than the repo level.

If we decide to leave it required, I can update the documentation when I add in the custom locker docs to encourage users to use locking appropriate for their use case and custom datastores, such as storing their lock on S3 if their datastore is there.

fix: failing tests

test: add a lock test suite

doc: update repo docs for custom locking
@jacobheun jacobheun changed the title feat(lock): allow for custom lock and no lock options feat(lock): allow for custom lock options Apr 16, 2018
@jacobheun
Copy link
Contributor Author

@dignifiedquire @diasdavid

I've made a few updates after everyones feedback:

  1. Documentation has been added to the Readme to help users see how to add a custom lock
  2. I have removed the ability to disable locking, so this feature update can focus on the customization aspect only. This should give users the ability to add appropriate locking based on their datastore types.
  3. I've added a suite to test that locks are being applied and that locking enforces one Node per Repo.

I also updated the repo options to allow for overloading of the lock option as a string or Lock, instead of a separate property. As @Mr0grog mentioned, I also think this is more friendly for users. I noted that specifying lock as a string is Deprecated, but it is still currently supported to allow for backwards compatibility.

dignifiedquire
dignifiedquire previously approved these changes Apr 17, 2018
Copy link
Member

@dignifiedquire dignifiedquire left a comment

Choose a reason for hiding this comment

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

thanks, looks much better now

Copy link

@Mr0grog Mr0grog left a comment

Choose a reason for hiding this comment

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

Added some quick thoughts on the docs. Looks good!

README.md Outdated
@@ -142,7 +142,7 @@ Arguments:

* `path` (string, mandatory): the path for this repo
* `options` (object, optional): may contain the following values
* `lock` (string, defaults to `"fs"` in Node.js, `"memory"` in the browser): what type of lock to use. Lock has to be acquired when opening.
* `lock` (string *Deprecated* or [Lock](#lock)), string can be `"fs"` or `"memory"`: what type of lock to use. Lock has to be acquired when opening.
Copy link

Choose a reason for hiding this comment

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

I think it’s generally clearer (and helps encourage correct usage) to describe the intended or standard usage first, then what’s deprecated or not desired — so I think it might be better to describe using an actual Lock type first, then describe the deprecated string support.

README.md Outdated

```js
const fsLock = require('ipfs-repo/src/lock') // Default in Node.js
const memLock = require('ipfs-repo/src/lock-memory') // Default in browser
Copy link

Choose a reason for hiding this comment

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

When it comes to examples and documentation, where a reader might not be familiar with all the concepts or names being used, it helps to avoid abbreviation if you can (so memoryLock might be better than memLock here).

README.md Outdated
const memLock = require('ipfs-repo/src/lock-memory') // Default in browser
```

#### `lock.open (dir, callback)`
Copy link

Choose a reason for hiding this comment

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

Isn’t this lock.lock (directory, callback)?

Also, it might help to preface this section with a sentence that says:

You can also provide your own custom Lock. It must be an object with the following interface:

README.md Outdated

#### `lock.open (dir, callback)`

Sets the lock if one does not already exist.
Copy link

Choose a reason for hiding this comment

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

It should also call callback(error) with an error if a lock does exist, right?

src/index.js Outdated
* @returns {void}
*/
_openLock (path, callback) {
this._locker.lock(path, callback)
Copy link

Choose a reason for hiding this comment

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

Since this can be user-provided now, should we validate that the resulting object has a close() method? (If yes, we probably also need to change _closeLock so it doesn’t try and close the unclose-able lock when handling the error 😛)

Ensure locks have a close method when creating the lock
@jacobheun
Copy link
Contributor Author

@Mr0grog I updated things based on your comments, and I agree we should check for the lock.close method. I updated the code and added a test to verify it. If the assertion error is triggered, the internal lockfile reference won't be set, so _closeLock won't get called.

Copy link
Member

@daviddias daviddias left a comment

Choose a reason for hiding this comment

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

Looking HAWT 🔥

@daviddias daviddias merged commit 460dafb into master Apr 23, 2018
@daviddias daviddias deleted the feat/locker branch April 23, 2018 08:47
@ghost ghost removed the status/in-progress In progress label Apr 23, 2018
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.

Allow the repo locker to be passed by configuration
4 participants