Skip to content

Support read-after-write consistency for NodeGraph bucket operations #244

@joshuakarp

Description

@joshuakarp

Specification

There's currently an issue of "read-after-write" consistency with sequences of batch operations in the NodeGraph buckets database, as setNode operations rely on the state of the bucket on insertion.

Recall that a bucket has a fixed capacity of k nodes. If we attempt to add a new node to a full bucket, we find the least active node in the bucket and remove it, in favour of the new node.

However, we come across an issue if we want to create a batch operation of multiple setNodeOps within the same bucket.

Because the ops are created before any additions, the bucket value is statically defined, based on the initial state of the bucket.

For example, if I were to batch add 3 nodes (A, B, C) into the same bucket (that already has some node Z, we'd have the following array of ops:

    [
      {
        type: 'put',
        domain: this.nodeGraphBucketsDbDomain,
        key: bucketIndex,
        value: {'Z':9.9.9.9, 'A':1.1.1.1},
      },
      {
        type: 'put',
        domain: this.nodeGraphBucketsDbDomain,
        key: bucketIndex,
        value: {'Z':9.9.9.9, 'B':2.2.2.2},
      },
      {
        type: 'put',
        domain: this.nodeGraphBucketsDbDomain,
        key: bucketIndex,
        value: {'Z':9.9.9.9, 'C':3.3.3.3},
      },
    ]

That is, the final setNode op would overwrite the entire bucket with only nodes Z and C in the bucket.

This problem can be solved by utilising the same system in js-encryptedfs. We'd need to use:

  • separate sublevels for each individual bucket index
  • Transaction snapshot system

In this process, it would also be worthwhile to change our keys to be buffers.

Additional context

Tasks

  1. Investigate the snapshot system in the EFS Transaction class
  2. Change buckets to use individual sublevels for each bucket index (instead of a single sublevel indexed by bucket indexes - see how RFS)
  3. Add "higher" metadata level for storing the size of a particular bucket. See INodeManager sublevel vs INodeManager dir sublevel. The INodeManager sublevel is capable of storing metadata.
  4. Incorporate transaction system into NodeGraph operations
  5. Remove lexicographic-integer dependency from PK (see original comments regarding this here https://gitlab.com/MatrixAI/Engineering/Polykey/js-polykey/-/merge_requests/205#note_707121227)

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdevelopmentStandard developmentepicBig issue with multiple subissuesr&d:polykey:core activity 4End to End Networking behind Consumer NAT Devices

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions