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(layered-storage): add a new storage for options #71

Draft
wants to merge 54 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
d4476da
feat(layered-storage): add a new storage for options
Thomaash Dec 8, 2019
285977d
feat(layered-storage): return off function from on
Thomaash Dec 9, 2019
4b49dc1
docs(layered-storage): add some docs
Thomaash Dec 9, 2019
9fb537a
docs(layered-storage): add yet more docs
Thomaash Dec 11, 2019
357b951
docs(layered-storage): add docs to transactions
Thomaash Dec 12, 2019
353f220
style(layered-storage): rename revert to abort
Thomaash Dec 12, 2019
47bfa2f
docs(layered-storage): finish the docs
Thomaash Dec 12, 2019
bfb7012
test(layered-storage): check that off unbinds listeners
Thomaash Dec 12, 2019
b2f0408
fix(layered-storage): fix unwritten segments being undefined
Thomaash Dec 14, 2019
85ea039
fix(layered-storage): cache the values when accessed
Thomaash Dec 14, 2019
e5d429c
fix(layered-storage): throw for nonnumeric layers
Thomaash Dec 14, 2019
689c154
feat(layered-storage): add console dump method
Thomaash Dec 14, 2019
b6f13b8
fix(layered-storage): purge empty structures
Thomaash Dec 15, 2019
7c4350c
fix(layered-storage): do not create new structures on access
Thomaash Dec 15, 2019
d9eb64c
style: fix linting issues
Thomaash Dec 15, 2019
de132b4
feat(layered-storage): remove events
Thomaash Dec 17, 2019
24beaa2
style(layered-storage): remove unused import
Thomaash Dec 17, 2019
b1787b8
feat(layered-layout): add validation
Thomaash Dec 18, 2019
b64c4fd
perf(layered-storage): do not clean unaffacted cache
Thomaash Dec 23, 2019
4bf2f3a
perf(layered-storage): cache nonexistent values too
Thomaash Dec 25, 2019
80f189c
perf(layered-storage): iterate over cache when clearing it
Thomaash Dec 25, 2019
e87368a
feat(layered-storage): add expanders
Thomaash Dec 26, 2019
1ca06e1
feat(layered-storage): unify validator and expander API
Thomaash Dec 26, 2019
1fed169
feat(layered-storage): add segment cloning
Thomaash Dec 27, 2019
b9b559c
fix(layered-storage): use entries instead of pair
Thomaash Dec 27, 2019
9d61fa2
fix(layered-storage): sort debug output
Thomaash Dec 27, 2019
84f4d27
chore(layered-storage): fix some doc comments
Thomaash Jan 21, 2020
093040f
perf(layered-storage): improve performance
Thomaash Jan 21, 2020
fd2a42e
docs(layered-storage): update outdated comment
Thomaash Jan 21, 2020
84a0144
style(layered-storage): unify the way existence is checked in core
Thomaash Jan 21, 2020
cc0f866
feat(layered-storage): simplify
Thomaash Jan 26, 2020
cc7e879
fix(layered-storage): remove cyclic dep
Thomaash Jan 26, 2020
bf566ec
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash May 24, 2020
763c703
style: reformat
Thomaash May 24, 2020
28a1240
style: fix typo in config
Thomaash May 24, 2020
1153f4a
chore: restore package* from master
Thomaash May 24, 2020
41195bd
feat(layered-storage): add export to object
Thomaash May 24, 2020
6b3785b
fix(layered-storage): throw right away in transactions
Thomaash May 24, 2020
d229669
test(layered-storage): fix copy paste error
Thomaash May 24, 2020
d1c16b9
feat(layered-storage): add inheritance
Thomaash May 24, 2020
10367bb
feat(layered-storage): add a basic library of validators
Thomaash May 24, 2020
9175f38
feat(layered-storage)!: use sepparate input and output types
Thomaash May 31, 2020
9089b80
fix(layered-storage): expand keys recursively
Thomaash May 31, 2020
fb0fc8b
feat(layered-storage)!: add DELETE keyword to delete values through set
Thomaash May 31, 2020
ab56402
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash May 31, 2020
6c3c545
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash Jun 1, 2020
3a4b9f2
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash Jun 18, 2020
ab88903
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash Aug 9, 2020
edb0996
style(layered-storage): fix linting issues
Thomaash Aug 9, 2020
4d41b96
feat(layered-storage): add delete single layer from segment
Thomaash Aug 9, 2020
81fd0c3
Merge branch 'master' of github.com:visjs/vis-util into layered-storage
Thomaash Aug 9, 2020
15603e8
test: disable DTS testing for now
Thomaash Aug 9, 2020
97deb9b
style(eslint): fix automerging error
Thomaash Aug 9, 2020
501926e
fix(layered-storage): export it
Thomaash Aug 14, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat(layered-storage): add a new storage for options
This is intended to replace the prototype plus hacks insanity used at
the moment. However this is still WIP. There is no documentations yet
and more testing is necessary.

TODO:
- Add off.
- Write docs.
- Probably some other things too.

In a quick test I was able to resolve the issue discussed in
visjs/vis-network#178 and visjs/vis-network#213 with just a few lines of
code. Which is much better than the massive mess of weird hacks that
doesn't work reliably anyway.

Putting this to use will be a lot of work but fortunately it should be
possible to do it in parts. I would first use this in LayoutEngine and
EdgesHandler to resolve the forementioned issues and then probably one
module at the time.

Features:
- Encapsulates options merging.
- Explicit layer/segment/key structure instead of prototype chains.
- Observable.
- Overrides. *
- Type safety in TypeScript.

* Hierarchical layout is incompatible with smooth edges and has to
disable them. Overrides combined with observing easily and elegently
solve that. See the forementioned issues for current state.
  • Loading branch information
Thomaash committed Jan 26, 2020
commit d4476da24e961c3bbdc3a50b5bc32fe82ced6ff0
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -53,6 +53,8 @@ module.exports = {

// Empty functions are useful sometimes.
"@typescript-eslint/no-empty-function": "off",
// This would be great if TypeScript was perfect but sometimes tsc can't infer the correct type.
'@typescript-eslint/no-non-null-assertion': 'off',
// This is really crazy given the functions in this package.
"@typescript-eslint/no-explicit-any": "off",
// These are hoisted, I have no idea why it reports them by default.
93 changes: 93 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -125,6 +125,7 @@
"rollup-plugin-copy-glob": "^0.3.1",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-terser": "^5.1.3",
"rollup-plugin-typescript2": "^0.25.3",
"semantic-release": "^16.0.0",
"sinon": "^8.0.1",
"snap-shot-it": "^7.9.1",
5 changes: 5 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import babel from "rollup-plugin-babel";
import commonjs from "rollup-plugin-commonjs";
import copyGlob from "rollup-plugin-copy-glob";
import resolve from "rollup-plugin-node-resolve";
import typescript from "rollup-plugin-typescript2";
import { generateHeader } from "vis-dev-utils";
import { terser } from "rollup-plugin-terser";

@@ -12,6 +13,10 @@ const commonPlugins = [
extensions: [".ts", ".js", ".json"]
}),
commonjs(),
typescript({
objectHashIgnoreUnknownHack: true,
tsconfig: "tsconfig.code.json"
}),
babel({
extensions: [".ts", ".js"],
runtimeHelpers: true
6 changes: 6 additions & 0 deletions src/layered-storage/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type KeyRange = number | string | symbol;
export type KeyValueLookup = Record<KeyRange, any>;
export type LayerRange = number;
export type Segment = boolean | number | object | string | symbol;

export type EventCallback<Key> = (keys: Key[]) => void;
124 changes: 124 additions & 0 deletions src/layered-storage/core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { KeyValueLookup, LayerRange, Segment } from "./common";

const reverseNumeric = (a: number, b: number): number => b - a;

export class LayeredStorageCore<
KeyValue extends KeyValueLookup,
Layer extends LayerRange
> {
public monolithic = Symbol("Monolithic");

private _data = new Map<
Layer,
Map<Segment, Map<keyof KeyValue, KeyValue[keyof KeyValue]>>
>();

private _layers: Layer[] = [];
private readonly _segments = new Set<Segment>();

private readonly _topLevelCache = new Map<
Segment,
Map<keyof KeyValue, KeyValue[keyof KeyValue]>
>();

private _updateCache(key: keyof KeyValue): void {
segmentsLoop: for (const segment of this._segments) {
const sCache =
this._topLevelCache.get(segment) ||
this._topLevelCache.set(segment, new Map()).get(segment)!;

sCache.delete(key);

for (const layer of this._layers) {
const lsData = this._getLSData(layer, segment);
if (lsData.has(key)) {
sCache.set(key, lsData.get(key)!);
continue segmentsLoop;
}

const lmData = this._getLSData(layer, this.monolithic);
if (lmData.has(key)) {
sCache.set(key, lmData.get(key)!);
continue segmentsLoop;
}
}
}
}

private _getLSData(
layer: Layer,
segment: Segment
): Map<keyof KeyValue, KeyValue[keyof KeyValue]> {
let lData = this._data.get(layer);
if (lData == null) {
lData = new Map();
this._data.set(layer, lData);

this._layers = [...this._data.keys()].sort(reverseNumeric);
}

let lsData = lData.get(segment);
if (lsData == null) {
lsData = new Map();
lData.set(segment, lsData);

this._segments.add(segment);
}

return lsData;
}

public get<Key extends keyof KeyValue>(
segment: Segment,
key: Key
): KeyValue[Key] | undefined {
const sData = this._topLevelCache.get(segment);
if (sData == null) {
return;
}

return sData.get(key);
}

public has<Key extends keyof KeyValue>(segment: Segment, key: Key): boolean {
const sData = this._topLevelCache.get(segment);
if (sData == null) {
return false;
}

return sData.has(key);
}

public set<Key extends keyof KeyValue>(
layer: Layer,
segment: Segment,
key: Key,
value: KeyValue[Key]
): void {
const lsData = this._getLSData(layer, segment);
lsData.set(key, value);

this._updateCache(key);
}

public delete<Key extends keyof KeyValue>(
layer: Layer,
segment: Segment,
key: Key
): boolean {
const lsData = this._getLSData(layer, segment);
const didItExist = lsData.delete(key);

this._updateCache(key);

return didItExist;
}

public deleteSegmentData(segment: Segment): void {
for (const lData of this._data.values()) {
lData.delete(segment);
}
this._topLevelCache.delete(segment);
this._segments.delete(segment);
}
}
7 changes: 7 additions & 0 deletions src/layered-storage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {
LayeredStorage,
LayeredStorageSegmentTransaction,
LayeredStorageTransaction
} from "./layered-storage";
export { LayeredStorageSegment } from "./segment";
export { EventCallback, KeyValueLookup, LayerRange, Segment } from "./common";
Loading