Skip to content

Commit 74bdc26

Browse files
committed
state transition logs - WIP
1 parent be67698 commit 74bdc26

File tree

3 files changed

+246
-2
lines changed

3 files changed

+246
-2
lines changed

src/data/history.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export * from './history/BFSHistoryWalk';
22
export * from './history/FullHistoryWalk';
33
export * from './history/HistoryDelta';
44
export * from './history/HistoryWalk';
5-
export * from './history/OpHeader';
5+
export * from './history/OpHeader';
6+
export * from './history/HistoryFragment';

src/data/history/HistoryLog.ts

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
import { Hash, HashedObject, HashedSet, MutableObject, MutationOp } from '../model';
2+
import { HistoryFragment } from '../history';
3+
import { MultiMap } from 'util/multimap';
4+
import { ArrayMap } from 'util/arraymap';
5+
6+
class StateTransition<T extends MutableObject> extends MutationOp {
7+
8+
static className = 'hss/v0/HistoryLog/StateTransition';
9+
10+
mutableHash?: Hash;
11+
start?: Hash;
12+
end?: Hash;
13+
14+
info?: any;
15+
16+
constructor(log: HistoryLog<T>, mutableHash?: Hash, start?: Hash, end?: Hash, info?: any) {
17+
super(log);
18+
19+
this.mutableHash = mutableHash;
20+
this.start = start;
21+
this.end = end;
22+
23+
this.info = info;
24+
}
25+
26+
getClassName(): string {
27+
return StateTransition.className;
28+
}
29+
30+
init(): void {
31+
32+
}
33+
34+
async validate(references: Map<string, HashedObject>): Promise<boolean> {
35+
return await super.validate(references) &&
36+
typeof(this.mutableHash) === 'string' &&
37+
(this.start === undefined || typeof(this.start) === 'string') &&
38+
typeof(this.end) === 'string' &&
39+
(this.info === undefined || HashedObject.isLiteral(this.info));
40+
}
41+
}
42+
43+
class VerifiedStateTransition<T extends MutableObject> extends StateTransition<T> {
44+
45+
static className = 'hss/v0/HistoryLog/VerifiedStateTransition';
46+
47+
mutable?: T;
48+
ops?: HashedSet<MutationOp>;
49+
50+
constructor(log: HistoryLog<T>, mutable?: T, start?: Hash, end?: Hash, info?: any, ops?: Map<Hash, MutationOp>) {
51+
super(log, mutable?.getLastHash(), start, end, info);
52+
53+
this.mutable = mutable;
54+
this.ops = new HashedSet(ops?.values());
55+
}
56+
getClassName(): string {
57+
return VerifiedStateTransition.className;
58+
}
59+
60+
async validate(references: Map<string, HashedObject>): Promise<boolean> {
61+
if (!(await super.validate(references))) {
62+
return false;
63+
}
64+
65+
if (this.mutable?.getLastHash() !== this.mutableHash) {
66+
return false;
67+
}
68+
69+
const frag = new HistoryFragment(this.mutableHash as Hash);
70+
71+
if (!(this.ops instanceof HashedSet)) {
72+
return false;
73+
}
74+
75+
for (const op of this.ops?.values()) {
76+
if (!(op instanceof MutationOp)) {
77+
return false;
78+
}
79+
80+
if (!(op.getTargetObject().getLastHash() !== this.mutable?.getLastHash())) {
81+
return false;
82+
}
83+
84+
const opHeader = await this.mutable?.getOpHeader(op.getLastHash());
85+
86+
if (opHeader === undefined) {
87+
return false;
88+
}
89+
90+
frag.add(opHeader);
91+
}
92+
93+
const start = new HashedSet<Hash>(frag.getStartingOps().values());
94+
const end = new HashedSet<Hash>(frag.getTerminalOps().values());
95+
96+
if (this.start !== start.hash()) {
97+
return false;
98+
}
99+
100+
if (this.end !== end.hash()) {
101+
return false;
102+
}
103+
104+
return true;
105+
}
106+
}
107+
108+
class HistoryLogEntry<T extends MutableObject> extends MutationOp {
109+
110+
static className = 'hss/v0/HistoryLog/Entry';
111+
112+
transitions?: HashedSet<StateTransition<T>>;
113+
114+
constructor(transitions?: HashedSet<StateTransition<T>>) {
115+
super();
116+
this.transitions = transitions;
117+
}
118+
119+
getClassName(): string {
120+
return HistoryLogEntry.className;
121+
}
122+
123+
init(): void {
124+
125+
}
126+
127+
async validate(references: Map<string, HashedObject>): Promise<boolean> {
128+
129+
if (!(await super.validate(references))) {
130+
return false;
131+
}
132+
133+
if (!(this.transitions instanceof HashedSet)) {
134+
return false;
135+
}
136+
137+
//const seen = new Set<Hash>();
138+
139+
for (const transition of this.transitions.values()) {
140+
141+
if (!(transition instanceof StateTransition)) {
142+
return false;
143+
}
144+
145+
/*if (seen.has(transition.mutable as Hash)) {
146+
return false;
147+
}
148+
149+
seen.add(transition.mutable as Hash);*/
150+
}
151+
152+
return true;
153+
}
154+
155+
}
156+
157+
abstract class HistoryLog<T extends MutableObject> extends MutableObject {
158+
159+
_transitions: ArrayMap<Hash, StateTransition<T>>;
160+
_pending: ArrayMap<Hash, StateTransition<T>>;
161+
162+
_faulted: MultiMap<Hash, StateTransition<T>>;
163+
164+
constructor() {
165+
super([StateTransition.className, VerifiedStateTransition.className, HistoryLogEntry.className], {supportsUndo: false});
166+
167+
this._transitions = new ArrayMap(false);
168+
this._pending = new ArrayMap(false);
169+
170+
this._faulted = new MultiMap();
171+
}
172+
173+
async attemptTransition(fragment: HistoryFragment, timeout?: number): Promise<HistoryLogEntry<T>> {
174+
175+
timeout;
176+
177+
this.createAttemptTransitionOp(fragment);
178+
179+
throw new Error('Unfinished');
180+
}
181+
async attemptVerifiedTransition(fragment: HistoryFragment, mut: T, ops: Map<Hash, MutationOp>, timeout?: number): Promise<boolean> {
182+
183+
timeout;
184+
185+
this.createAttemptTransitionOp(fragment, mut, ops);
186+
187+
throw new Error('Unfinished');
188+
}
189+
190+
private async createAttemptTransitionOp(fragment: HistoryFragment, mut?: T, ops?: Map<Hash, MutationOp>) {
191+
fragment; mut; ops;
192+
throw new Error('unfinished');
193+
}
194+
195+
getLastTransition(mut: Hash): (StateTransition<T>|undefined) {
196+
197+
const txs = this._transitions.get(mut);
198+
199+
if (txs.length > 0) {
200+
return txs[-1];
201+
} else {
202+
return undefined;
203+
}
204+
205+
}
206+
207+
mutate(op: MutationOp, valid: boolean, cascade: boolean): Promise<boolean> {
208+
209+
valid; cascade;
210+
211+
if (op instanceof StateTransition) {
212+
213+
this._pending.add(op.mutableHash as Hash, op);
214+
} else if (op instanceof HistoryLogEntry) {
215+
216+
}
217+
218+
throw new Error('unfinished')
219+
}
220+
221+
getMutableContents(): MultiMap<string, HashedObject> {
222+
return new MultiMap();
223+
}
224+
225+
getMutableContentByHash(_hash: string): Set<HashedObject> {
226+
return new Set();
227+
}
228+
229+
getClassName(): string {
230+
throw new Error('Method not implemented.');
231+
}
232+
233+
init(): void {
234+
throw new Error('Method not implemented.');
235+
}
236+
237+
validate(_references: Map<string, HashedObject>): Promise<boolean> {
238+
throw new Error('Method not implemented.');
239+
}
240+
241+
}
242+
243+
export { HistoryLog };

src/data/model/mutable/MutableObject.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const ContentChangeEventActions: Array<string> = [MutableContentEvents.AddObject
3030

3131
type MutableObjectConfig = {supportsUndo?: boolean};
3232

33-
abstract class MutableObject extends HashedObject {
33+
abstract class MutableObject extends HashedObject {
3434

3535
static controlLog = new Logger(MutableObject.name, LogLevel.INFO)
3636
static prevOpsComputationLog = new Logger(MutableObject.name, LogLevel.INFO);

0 commit comments

Comments
 (0)