@classroomtechtools/object-store
v1.0.0
Published
A key/value store in AppsScripts that stores values and objects locally in memory, and writes to the `CacheService` and `PropertiesService` for reliable persistance.
Downloads
2
Readme
Object Store
A key/value store in AppsScripts that stores values and objects locally in memory, and writes to the CacheService
and PropertiesService
for reliable persistance.
It operates in two modes, auto or manual, the latter of which gives you control of when objects are persisted.
// "global" stores, choose from 'script', 'document' or 'user'
const autoStore = ObjectStore.create(); // 'script by default'
const manualStore = ObjectStore.create('script', {manual: true});
function autopersist () {
// persisted now:
autoStore.set('key', {value: 'value'});
... // on next execution
const value = autoStore.get('key');
}
function manuallypersist () {
const dataArray = [ {idx: 1, d: 'd'}, ... ];
for (const item of dataArray) {
// keys must be strings (throws error if not):
const key = item.idx.toString();
// does not persist in PropertiesStorage yet:
manualStore.set(key, item);
}
// manually tell it to persist, more performant
manualStore.persist();
}
Get Started:
- Library ID:
1vAC2ffoTeBPU6SmGTEBsQuf-XP_Pv-XaTUCNHscyGmiJRCNHZhevGEz6
- Documentation
How it works
A key/value store is just nomenclature where you have some sort of identifier (usually a string) that coorrelates to a value or object. JavaScript Objects can be a key/value store, and so are the Properties
and Cache
objects.
In V8 JavaScript, the new datastructure Map
is also a key/value store, and is used internally by this library to store objects natively. When it persists, it writes to the PropertiesService
service.
Why?
AppsScripters need a quick and easy way to keep objects hanging around, and to persist them across executions. There are services available but using them effectively is a well-worn problem. Why not solve it once-and-for-all?
Using PropertiesService
is great for persisting across executions, but is slow and has a quota. If you're storing objects, you'll need to parse them to use them first, making it even slower.
Using the CacheService
is much faster but has a time limit, and you have to consult that first, before using PropertiesService. You'll also need to stringify those objects.
Keeping them locally in memory is fastest, and doesn't have to be stringified. However, once the execution stops, you'll have to persist them somehow, either in the cache or store.
This libray does all three, so you don't have to worry about it.
Examples
This illustrates the basic methods and properties:
const store = ObjectStore(); // by default uses script
// store an item, can even be a date
store.set('key', {});
store.set('key', new Date());
// get them back
store.get('key');
//delete them
store.remove('key');
// access the internals:
store.cache; // instance of Cache
store.props; // instance of Properites
store.map; // instance of Map object
This is how you use it to manually tell it to persist:
// turn on manual mode
const store = ObjectStore.create('script', {manual: true});
// store a bunch of objects
const arr = [{a:'a'}, {b: 'b'} ...];
arr.forEach(function (item, index) {
store.set(index.toString(), item);
});
// persist after the loop:
store.persist();
Performance Note
With only 10 items in the array, persisting it manually rather than in the each time through a loop is compared with the following code:
function speedtest() {
const props = PropertiesService.getScriptProperties();
[null, false, true].forEach( manual => {
const max = 10;
const arr = Array.from(Array(max).keys());
const store = create('script', {manual}); // just save to local
store.removeAll(arr); // resets it from previous call
const start = new Date().getTime();
arr.map(item => (max - item).toString())
.forEach( (num, idx) => {
const item = {idx, a: num, date: new Date()};
if (manual == null)
props.setProperty(num, JSON.stringify(item));
else
store.set(num, item, skipCache=true);
});
if (manual)
store.persist(); // now save
const end = new Date().getTime();
Logger.log(manual + ': ' + ((end - start) / 1000) + ' seconds');
});
}
Result:
For max = 10:
null: 1.049 seconds # Calling PropertiesService directly
false: 1.041 seconds # In auto mode (persisting during loop)
true: 0.068 seconds # In manual mode (persisting after loop)
For max = 100:
null: 9.269 seconds
false: 6.476 seconds
true: 0.072 seconds
For max = 1000:
null: 68.854 seconds
false: 68.777 seconds
true: 0.139 seconds
Note that skipCache
was set to true
in calls to set
in order to present a more reliable metric of comparison.
Conclusion: There could be substantial performance benefit to using this library in manual mode.