Skip to content

Commit

Permalink
Merge pull request #143 from tompng/model_self_destroy
Browse files Browse the repository at this point in the history
Model self destroy
  • Loading branch information
tompng authored Jul 4, 2024
2 parents 33ee0e1 + f49bae6 commit a29aea7
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 129 deletions.
22 changes: 10 additions & 12 deletions core/ArSyncModel.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { ArSyncStore, Request } from './ArSyncStore';
import ConnectionAdapter from './ConnectionAdapter';
interface Request {
api: string;
query: any;
params?: any;
}
declare type Path = Readonly<(string | number)[]>;
interface Change {
path: Path;
Expand All @@ -12,8 +8,14 @@ interface Change {
declare type ChangeCallback = (change: Change) => void;
declare type LoadCallback = () => void;
declare type ConnectionCallback = (status: boolean) => void;
declare type SubscriptionType = 'load' | 'change' | 'connection';
declare type SubscriptionType = 'load' | 'change' | 'connection' | 'destroy';
declare type SubscriptionCallback = ChangeCallback | LoadCallback | ConnectionCallback;
declare type ArSyncModelRef = {
key: string;
count: number;
timer: number | null;
model: ArSyncStore;
};
declare type PathFirst<P extends Readonly<any[]>> = ((...args: P) => void) extends (first: infer First, ...other: any) => void ? First : never;
declare type PathRest<U> = U extends Readonly<any[]> ? ((...args: U) => any) extends (head: any, ...args: infer T) => any ? U extends Readonly<[any, any, ...any[]]> ? T : never : never : never;
declare type DigResult<Data, P extends Readonly<any[]>> = Data extends null | undefined ? Data : PathFirst<P> extends never ? Data : PathFirst<P> extends keyof Data ? (Data extends Readonly<any[]> ? undefined : never) | {
Expand All @@ -26,6 +28,7 @@ export default class ArSyncModel<T> {
private _listeners;
complete: boolean;
notfound?: boolean;
destroyed: boolean;
connected: boolean;
data: T | null;
static _cache: {
Expand All @@ -52,12 +55,7 @@ export default class ArSyncModel<T> {
release(): void;
static retrieveRef(request: Request, option?: {
immutable: boolean;
}): {
key: string;
count: number;
timer: number | null;
model: any;
};
}): ArSyncModelRef;
static _detach(ref: any): void;
private static _attach;
static setConnectionAdapter(adapter: ConnectionAdapter): void;
Expand Down
12 changes: 7 additions & 5 deletions core/ArSyncModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ var ConnectionManager_1 = require("./ConnectionManager");
var ArSyncModel = /** @class */ (function () {
function ArSyncModel(request, option) {
var _this = this;
this.complete = false;
this.destroyed = false;
this._ref = ArSyncModel.retrieveRef(request, option);
this._listenerSerial = 0;
this._listeners = {};
this.complete = false;
this.connected = ArSyncStore_1.default.connectionManager.networkStatus;
this.connected = ArSyncStore_1.ArSyncStore.connectionManager.networkStatus;
var setData = function () {
_this.data = _this._ref.model.data;
_this.complete = _this._ref.model.complete;
_this.notfound = _this._ref.model.notfound;
_this.destroyed = _this._ref.model.destroyed;
};
setData();
this.subscribe('load', setData);
this.subscribe('change', setData);
this.subscribe('destroy', setData);
this.subscribe('connection', function (status) {
_this.connected = status;
});
Expand Down Expand Up @@ -81,13 +84,12 @@ var ArSyncModel = /** @class */ (function () {
this._listeners[id].unsubscribe();
this._listeners = {};
ArSyncModel._detach(this._ref);
this._ref = null;
};
ArSyncModel.retrieveRef = function (request, option) {
var key = JSON.stringify([request, option]);
var ref = this._cache[key];
if (!ref) {
var model = new ArSyncStore_1.default(request, option);
var model = new ArSyncStore_1.ArSyncStore(request, option);
ref = this._cache[key] = { key: key, count: 0, timer: null, model: model };
}
this._attach(ref);
Expand Down Expand Up @@ -116,7 +118,7 @@ var ArSyncModel = /** @class */ (function () {
clearTimeout(ref.timer);
};
ArSyncModel.setConnectionAdapter = function (adapter) {
ArSyncStore_1.default.connectionManager = new ConnectionManager_1.default(adapter);
ArSyncStore_1.ArSyncStore.connectionManager = new ConnectionManager_1.default(adapter);
};
ArSyncModel.waitForLoad = function () {
var models = [];
Expand Down
14 changes: 11 additions & 3 deletions core/ArSyncStore.d.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
export default class ArSyncStore {
export declare type Request = {
api: string;
query: any;
params?: any;
id?: any;
};
export declare class ArSyncStore {
immutable: boolean;
markedForFreezeObjects: any[];
changes: any;
eventListeners: any;
markForRelease: true | undefined;
container: any;
request: any;
request: Request;
complete: boolean;
notfound?: boolean;
destroyed: boolean;
data: any;
changesBufferTimer: number | undefined | null;
retryLoadTimer: number | undefined | null;
static connectionManager: any;
constructor(request: any, { immutable }?: {
constructor(request: Request, { immutable }?: {
immutable?: boolean | undefined;
});
handleDestroy(): void;
load(retryCount: number): void;
setChangesBufferTimer(): void;
subscribe(event: any, callback: any): {
Expand Down
80 changes: 37 additions & 43 deletions core/ArSyncStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArSyncStore = void 0;
var ArSyncApi_1 = require("./ArSyncApi");
var ModelBatchRequest = /** @class */ (function () {
function ModelBatchRequest() {
Expand Down Expand Up @@ -95,6 +96,7 @@ var modelBatchRequest = new ModelBatchRequest;
var ArSyncContainerBase = /** @class */ (function () {
function ArSyncContainerBase() {
this.listeners = [];
this.parentModel = null;
}
ArSyncContainerBase.prototype.replaceData = function (_data, _sync_keys) { };
ArSyncContainerBase.prototype.initForReload = function (request) {
Expand Down Expand Up @@ -246,7 +248,7 @@ var ArSyncContainerBase = /** @class */ (function () {
return attributes;
return { attributes: attributes, as: column, params: params };
};
ArSyncContainerBase._load = function (_a, root) {
ArSyncContainerBase.load = function (_a, root) {
var api = _a.api, id = _a.id, params = _a.params, query = _a.query;
var parsedQuery = ArSyncRecord.parseQuery(query);
var compactQueryAttributes = ArSyncRecord.compactQueryAttributes(parsedQuery);
Expand All @@ -255,7 +257,7 @@ var ArSyncContainerBase = /** @class */ (function () {
if (!data)
throw { retry: false };
var request = { api: api, id: id, query: compactQueryAttributes };
return new ArSyncRecord(parsedQuery, data, request, root);
return new ArSyncRecord(parsedQuery, data, request, root, null, null);
});
}
else {
Expand All @@ -265,39 +267,22 @@ var ArSyncContainerBase = /** @class */ (function () {
throw { retry: false };
}
else if (response.collection && response.order) {
return new ArSyncCollection(response.sync_keys, 'collection', parsedQuery, response, request_1, root);
return new ArSyncCollection(response.sync_keys, 'collection', parsedQuery, response, request_1, root, null, null);
}
else if (response instanceof Array) {
return new ArSyncCollection([], '', parsedQuery, response, request_1, root);
return new ArSyncCollection([], '', parsedQuery, response, request_1, root, null, null);
}
else {
return new ArSyncRecord(parsedQuery, response, request_1, root);
return new ArSyncRecord(parsedQuery, response, request_1, root, null, null);
}
});
}
};
ArSyncContainerBase.load = function (apiParams, root) {
var _this = this;
if (!(apiParams instanceof Array))
return this._load(apiParams, root);
return new Promise(function (resolve, _reject) {
var resultModels = [];
var countdown = apiParams.length;
apiParams.forEach(function (param, i) {
_this._load(param, root).then(function (model) {
resultModels[i] = model;
countdown--;
if (countdown === 0)
resolve(resultModels);
});
});
});
};
return ArSyncContainerBase;
}());
var ArSyncRecord = /** @class */ (function (_super) {
__extends(ArSyncRecord, _super);
function ArSyncRecord(query, data, request, root) {
function ArSyncRecord(query, data, request, root, parentModel, parentKey) {
var _this = _super.call(this) || this;
_this.fetching = new Set();
_this.root = root;
Expand All @@ -307,7 +292,10 @@ var ArSyncRecord = /** @class */ (function (_super) {
_this.queryAttributes = query.attributes || {};
_this.data = {};
_this.children = {};
_this.rootRecord = !parentModel;
_this.replaceData(data);
_this.parentModel = parentModel;
_this.parentKey = parentKey;
return _this;
}
ArSyncRecord.prototype.setSyncKeys = function (sync_keys) {
Expand All @@ -333,12 +321,10 @@ var ArSyncRecord = /** @class */ (function (_super) {
child.replaceData(subData, this.sync_keys);
}
else {
var collection = new ArSyncCollection(this.sync_keys, key, subQuery, subData, null, this.root);
var collection = new ArSyncCollection(this.sync_keys, key, subQuery, subData, null, this.root, this, aliasName);
this.mark();
this.children[aliasName] = collection;
this.data[aliasName] = collection.data;
collection.parentModel = this;
collection.parentKey = aliasName;
}
}
else {
Expand All @@ -349,12 +335,10 @@ var ArSyncRecord = /** @class */ (function (_super) {
child.replaceData(subData);
}
else {
var model = new ArSyncRecord(subQuery, subData, null, this.root);
var model = new ArSyncRecord(subQuery, subData, null, this.root, this, aliasName);
this.mark();
this.children[aliasName] = model;
this.data[aliasName] = model.data;
model.parentModel = this;
model.parentKey = aliasName;
}
}
else {
Expand Down Expand Up @@ -406,15 +390,13 @@ var ArSyncRecord = /** @class */ (function (_super) {
_this.fetching.delete(fetchKey_1);
if (!data || !_this.data)
return;
var model = new ArSyncRecord(query, data, null, _this.root);
var model = new ArSyncRecord(query, data, null, _this.root, _this, aliasName);
var child = _this.children[aliasName];
if (child)
child.release();
_this.children[aliasName] = model;
_this.mark();
_this.data[aliasName] = model.data;
model.parentModel = _this;
model.parentKey = aliasName;
_this.onChange([aliasName], model.data);
}).catch(function (e) {
console.error("failed to load " + className + ":" + id + " " + e);
Expand Down Expand Up @@ -452,6 +434,13 @@ var ArSyncRecord = /** @class */ (function (_super) {
var path = _c[_b];
_loop_1(path);
}
if (this.rootRecord) {
var destroyCallback = function () { return _this.root.handleDestroy(); };
for (var _d = 0, _e = this.sync_keys; _d < _e.length; _d++) {
var key = _e[_d];
this.subscribe(key + '_destroy', destroyCallback);
}
}
};
ArSyncRecord.prototype.patchQuery = function (key) {
var _a;
Expand Down Expand Up @@ -500,14 +489,14 @@ var ArSyncRecord = /** @class */ (function (_super) {
return;
this.data = __assign({}, this.data);
this.root.mark(this.data);
if (this.parentModel)
if (this.parentModel && this.parentKey)
this.parentModel.markAndSet(this.parentKey, this.data);
};
return ArSyncRecord;
}(ArSyncContainerBase));
var ArSyncCollection = /** @class */ (function (_super) {
__extends(ArSyncCollection, _super);
function ArSyncCollection(sync_keys, path, query, data, request, root) {
function ArSyncCollection(sync_keys, path, query, data, request, root, parentModel, parentKey) {
var _this = _super.call(this) || this;
_this.ordering = { orderBy: 'id', direction: 'asc' };
_this.aliasOrderKey = 'id';
Expand All @@ -525,6 +514,8 @@ var ArSyncCollection = /** @class */ (function (_super) {
_this.data = [];
_this.children = [];
_this.replaceData(data, sync_keys);
_this.parentModel = parentModel;
_this.parentKey = parentKey;
return _this;
}
ArSyncCollection.prototype.setOrdering = function (ordering) {
Expand Down Expand Up @@ -580,9 +571,7 @@ var ArSyncCollection = /** @class */ (function (_super) {
model.replaceData(subData);
}
else if (subData.sync_keys) {
model = new ArSyncRecord(this.query, subData, null, this.root);
model.parentModel = this;
model.parentKey = subData.id;
model = new ArSyncRecord(this.query, subData, null, this.root, this, subData.id);
}
if (model) {
newChildren.push(model);
Expand Down Expand Up @@ -647,9 +636,7 @@ var ArSyncCollection = /** @class */ (function (_super) {
_this.fetching.delete(id);
if (!data || !_this.data)
return;
var model = new ArSyncRecord(_this.query, data, null, _this.root);
model.parentModel = _this;
model.parentKey = id;
var model = new ArSyncRecord(_this.query, data, null, _this.root, _this, id);
var overflow = limit && limit <= _this.data.length;
var rmodel;
_this.mark();
Expand Down Expand Up @@ -755,23 +742,30 @@ var ArSyncCollection = /** @class */ (function (_super) {
return;
this.data = __spreadArrays(this.data);
this.root.mark(this.data);
if (this.parentModel)
if (this.parentModel && this.parentKey)
this.parentModel.markAndSet(this.parentKey, this.data);
};
return ArSyncCollection;
}(ArSyncContainerBase));
var ArSyncStore = /** @class */ (function () {
function ArSyncStore(request, _a) {
var immutable = (_a === void 0 ? {} : _a).immutable;
this.complete = false;
this.destroyed = false;
this.immutable = !!immutable;
this.markedForFreezeObjects = [];
this.changes = [];
this.eventListeners = { events: {}, serial: 0 };
this.request = request;
this.complete = false;
this.data = null;
this.load(0);
}
ArSyncStore.prototype.handleDestroy = function () {
this.release();
this.data = null;
this.destroyed = true;
this.trigger('destroy');
};
ArSyncStore.prototype.load = function (retryCount) {
var _this = this;
ArSyncContainerBase.load(this.request, this).then(function (container) {
Expand Down Expand Up @@ -869,4 +863,4 @@ var ArSyncStore = /** @class */ (function () {
};
return ArSyncStore;
}());
exports.default = ArSyncStore;
exports.ArSyncStore = ArSyncStore;
1 change: 1 addition & 0 deletions core/hooks.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface ModelStatus {
complete: boolean;
notfound?: boolean;
connected: boolean;
destroyed: boolean;
}
export declare type DataAndStatus<T> = [T | null, ModelStatus];
export interface Request {
Expand Down
Loading

0 comments on commit a29aea7

Please sign in to comment.