-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Specification
CDSS
Currently, VaultInternal
utilizes the create-destroy pattern. We're considering instead refactoring this into a create-destroy-start-stop pattern. This would allow us to align function usage between VaultManager
and VaultInternal
as follows:
VaultManager |
VaultInternal |
---|---|
createVault |
createVaultInternal |
openVault |
start |
closeVault |
stop |
destroyVault |
destroy |
The meat of the logic should now be in 2 static methods of VaultInternal
, representing "smart asynchronous creators" of VaultInternal
. These should be:
VaultInternal.createVaultInternal - creates a new vault from scratch, think `git init`
VaultInternal.cloneVaultInternal - clones a vault, think `git clone`
creating a VaultInternal
instance with new or existing state should use VaultInternal.createVaultInternal
. First time cloning of a vault should use VaultInternal.cloneVaultInternal
. Get all the isogit related side-effects (client-side logic) into these static methods, the VaultManager
would only manage any additional metadata.
The start
method now has to setup internal state, specifically Git state, it needs to initialize the repository and also perform the initial commit, however it has to be idempotent, so if these actions are already done, it won't bother with it.
The stop cannot stop
efs, because the EFS lifecycle is handled outside by VaultManager
The destroy
should then destroy the Vault internal state, however additional destruction management would have to occur inside the VaultManager which might mean it has to construct (and thus load into-memory) the instance before it can destroy it.
The cloning and pulling code should work using withF
and withG
as used by NodeConnectionManager
. The cloning and pulling will need to have access to the ACL domain to ensure that permissions are properly set. Because permission checking occurs inside VaultManager
and not VaultInternal
and occurs before VaultInternal
functions are executed, this would imply that VaultManager
has access to the ACL and is bound to the ACL. Which would mean the meat of logic discussed above should be in VaultManager
.
Metadata
The VaultInternal
now needs to maintain its own DB domain to store vault related metadata. 2 new properties are relevant:
dirty
- this is a Boolean that determines whether the vault is in a dirty state or notremote
- if this contains a stringnodeId:vaultId
, then this vault should be considered a "remote" vault and must be immutable - see Investigate usage of theremote
field for vault metadata optimisation #309 and No longer preserve vault ID oncloneVault
#253
The internal domain is better than storing a POJO in the VaultManager
. That logic should be removed in favor of VaultInternal
having it's own internal domain, which is more efficient and more flexible.
Additional metadata along with the dirty
Boolean can be added to enable us to fix #252. This will be important to ensure internal consistency of our vaults in the presence of program crashes and also inadvertent OS shutdowns or just program killing.
misc.
The implementations of the functions in VaultManager
would internally call the respective function above in VaultInternal
. This would also allow us to add any extra functionality that needs to be separate from the VaultInternal
functions into the VaultManager
. For example, on creation of a vault, there's a few factors that need to be considered:
- Locking:
VaultInternal
has no notion of the creation/destruction locks used in theObjectMap
structure, so this can be safely handled inVaultManager.createVault
/destroyVault
.
Conversely, we should remove any instances where we perform similar logic between the two corresponding functions, and ensure it's centralized in a single place.
Locking will be handled via two RWLock
locks. One lock for the object map in VaultManager
. The other lock for the VaultInternal
instance. The VaultManager
RWLock
will handle the life cycle of the VaultInternal
Instance. Write locking will be used for the creation/destroy lifecycle. read locking will be used with the WithVaults
when accessing the vaults. The VaultInternal
locking will be used for the respective readF/G
and writeF/G
functions.
Git repository: anything to do with git instantiation for the vault could also be centralised within VaultInternal.createVaultInternal
To ensure the integrity of the vaultName information we need to apply locking when reading and writing to the VaultName
->VaultId
mapping in the database. This is to ensure that when we check if a vaultName already exists in the mapping we can trust that this information is correct and avoid concurrency issues with vault creation and renaming.
Additional context
- As we discovered in Review and Refactor of
git/utils.ts
for Serving Vault Git Repositories #298, the usage of isogit is mostly client-side behavior. But server side behaviour is facilitated byVaultManager
and functions found insrc/git/utils.ts
. - original comment on this Introducing vault sharing and the restrictions of pulling and cloning with vault permissions #266 (comment) based on discussion in our review with @scottmmorris https://vimeo.com/manage/videos/652339635
- discussion of
VaultInternal
(fromcommit
to end), as well as some discussion of CDSS withVaultInternal
https://vimeo.com/manage/videos/652700328
A note on usage of the CDSS pattern:
create...
: performs the dependency side-effects (i.e. creates any encapsulated dependencies before creating itself). That is, we can see this function as outside the instance of the classstart
: performs the side-effects on the created instance (with the created instance coming from the constructor)
tasks
- Convert
VaultInternal
to using the CDSS async-init pattern.- create a
createVaultInternal
constructor for creating aVaultInternal
instance on new or existing state. - create a
cloneVaultInternal
constructor for first time cloning of a vault. - all isogit related side effects and creating logic should be within these creation methods. Ideally
VaultManager
shouldn't touch isogit at all. -
start
method handles the creation of any state. This should be idempotent. this also handles anydb
domain creation. -
destroy
should destroy allVaultInternal
state.
- create a
- Cloning and pulling should use the with functions through the
NodeConnectionManager
. - permissions will need to be checked before cloning and pulling.
- Move handling of metadata to inside of
VaultInternal
- Implement a
dirty
field for tracking if the git repo is in a dirty state. - Implement a
remote
containing stringnodeId:vaultId
for tracking remote node and vault. this is also used to check if the vault is immutable. - Any other metadata needs to be moved here as well.
- Add ability to VaultManager to access the metadata for checking if a vault exists and checking/updating vaultName.
- Implement a
- Update
VaultManager
andVaultInternal
to useRWLock
locks.- Use object map write locking for
VaultInternal
lifecycle. - Use object map readLocking for accessing
VaultInternal
contents. - Use
VaultInternal
write/read locking for the read/write functions. -
VaultManager
git handling functions should be using both read locks. -
VaultInternal.pullVault
should respect the write lock. - add locking for
vaultName
->vaultId
metadata.
- Use object map write locking for
- Review and update tests for...
-
VaultManager
object map life-cycle. -
VaultManager
object map locking. -
VaultInternal
life-cycle. -
VaultInternal
locking. - git clone/pull permissions testing.
- concurrently creating vaults test.
- test for
VaultInternal.pullVault
locking
-