- 1 :
/**
- 2 :
* A class for simplying resource storage
- 3 :
* @memberof Spyral.Util
- 4 :
* @class
- 5 :
*/
- 6 :
class Storage {
- 7 :
- 8 :
constructor(config) {
- 9 :
this.MAX_LENGTH = 950000; // keep it under 1 megabyte
- 10 :
}
- 11 :
- 12 :
/**
- 13 :
* Store a resource
- 14 :
* @name Spyral.Util.Storage.storeResource
- 15 :
* @function
- 16 :
* @static
- 17 :
* @param {String} id
- 18 :
* @param {*} data
- 19 :
* @returns {Promise}
- 20 :
*/
- 21 :
static storeResource(id, data) {
- 22 :
var dataString = JSON.stringify(data);
- 23 :
- 24 :
if (dataString.length > this.MAX_LENGTH) {
- 25 :
// split into chunks
- 26 :
var promise = new Promise(function(resolve, reject) {
- 27 :
var numChunks = Math.ceil(dataString.length / this.MAX_LENGTH);
- 28 :
- 29 :
var chunkIds = [];
- 30 :
for (var i = 0; i < numChunks; i++) {
- 31 :
chunkIds.push(id+'-chunk'+i);
- 32 :
}
- 33 :
this._doStore(id+'-hasChunks', JSON.stringify(chunkIds)).then(function() {
- 34 :
var chunkCount = 0;
- 35 :
var currIndex = 0;
- 36 :
for (var i = 0; i < numChunks; i++) {
- 37 :
var chunkString = dataString.substr(currIndex, this.MAX_LENGTH);
- 38 :
- 39 :
this._doStore(chunkIds[i], chunkString).then(function() {
- 40 :
chunkCount++;
- 41 :
if (chunkCount == numChunks) {
- 42 :
resolve();
- 43 :
}
- 44 :
}, function() {
- 45 :
reject();
- 46 :
});
- 47 :
- 48 :
currIndex += this.MAX_LENGTH;
- 49 :
}
- 50 :
}.bind(this), function() {
- 51 :
reject();
- 52 :
});
- 53 :
}.bind(this));
- 54 :
- 55 :
return promise;
- 56 :
} else {
- 57 :
return this._doStore(id, dataString);
- 58 :
}
- 59 :
}
- 60 :
- 61 :
/**
- 62 :
* Get the URL for trombone
- 63 :
* @name Spyral.Util.Storage.getTromboneUrl
- 64 :
* @function
- 65 :
* @static
- 66 :
* @returns {String}
- 67 :
*/
- 68 :
static getTromboneUrl() {
- 69 :
return Voyant.application.getTromboneUrl();
- 70 :
}
- 71 :
- 72 :
static _doStore(id, dataString) {
- 73 :
return fetch(this.getTromboneUrl(), {
- 74 :
method: 'GET',
- 75 :
body: {
- 76 :
tool: 'resource.StoredResource',
- 77 :
resourceId: id,
- 78 :
storeResource: dataString
- 79 :
}
- 80 :
});
- 81 :
}
- 82 :
- 83 :
/**
- 84 :
* Get a stored resource
- 85 :
* @name Spyral.Util.Storage.getStoredResource
- 86 :
* @function
- 87 :
* @static
- 88 :
* @param {String} id
- 89 :
* @returns {Promise}
- 90 :
*/
- 91 :
static getStoredResource(id) {
- 92 :
return fetch(this.getTromboneUrl(), {
- 93 :
method: 'GET',
- 94 :
body: {
- 95 :
tool: 'resource.StoredResource',
- 96 :
verifyResourceId: id+'-hasChunks'
- 97 :
}
- 98 :
}).then(function(response) {
- 99 :
if (response.ok) {
- 100 :
response.json().then(json => {
- 101 :
if (json && json.storedResource && json.storedResource.id && json.storedResource.id !== '') {
- 102 :
// chunks
- 103 :
this._doGetStored(json.storedResource.id, false).then(function(chunkIds) {
- 104 :
var fullData = '';
- 105 :
var dataChunks = {};
- 106 :
for (var i = 0; i < chunkIds.length; i++) {
- 107 :
this._doGetStored(chunkIds[i], true).then(function(response) {
- 108 :
var chunkId = response[0];
- 109 :
var value = response[1];
- 110 :
dataChunks[chunkId] = value;
- 111 :
- 112 :
var done = true;
- 113 :
for (var j = chunkIds.length-1; j >= 0; j--) {
- 114 :
if (dataChunks[chunkIds[j]] === undefined) {
- 115 :
done = false;
- 116 :
break;
- 117 :
}
- 118 :
}
- 119 :
- 120 :
if (done) {
- 121 :
for (var j = 0; j < chunkIds.length; j++) {
- 122 :
fullData += dataChunks[chunkIds[j]];
- 123 :
}
- 124 :
return fullData;
- 125 :
}
- 126 :
}, function(err) {
- 127 :
throw Error('Storage: '+err)
- 128 :
});
- 129 :
}
- 130 :
}, function(err) {
- 131 :
throw Error('Storage: '+err)
- 132 :
});
- 133 :
} else {
- 134 :
// no chunks
- 135 :
return this._doGetStored(id, false).then(function(value) {
- 136 :
return value
- 137 :
}, function(err) {
- 138 :
throw Error('Storage: '+err)
- 139 :
});
- 140 :
}
- 141 :
});
- 142 :
} else {
- 143 :
- 144 :
}
- 145 :
});
- 146 :
}
- 147 :
- 148 :
static _doGetStored(id, isChunk) {
- 149 :
return fetch(this.getTromboneUrl(), {
- 150 :
method: 'GET',
- 151 :
body: {
- 152 :
tool: 'resource.StoredResource',
- 153 :
retrieveResourceId: id,
- 154 :
failQuietly: true
- 155 :
}
- 156 :
}).then(function(response) {
- 157 :
if (response.ok) {
- 158 :
response.json().then(json => {
- 159 :
var id = json.storedResource.id;
- 160 :
var value = json.storedResource.resource;
- 161 :
if (value.length == 0) {
- 162 :
throw Error('Storage: stored file is empty')
- 163 :
} else {
- 164 :
if (isChunk !== true) {
- 165 :
// value = JSON.parse(value);
- 166 :
return value;
- 167 :
} else {
- 168 :
return [id, value];
- 169 :
}
- 170 :
}
- 171 :
})
- 172 :
}
- 173 :
});
- 174 :
}
- 175 :
}
- 176 :
- 177 :
export default Storage