npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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

5

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.