Skip to content

Latest commit

 

History

History
232 lines (183 loc) · 7.59 KB

README.md

File metadata and controls

232 lines (183 loc) · 7.59 KB

logo

project status project stability

Momento JavaScript Client Library

JavaScript client SDK for Momento Serverless Cache: a fast, simple, pay-as-you-go caching solution without any of the operational overhead required by traditional caching solutions!

Getting Started 🏃

Requirements

  • Node version 14 or higher is required
  • A Momento Auth Token is required, you can generate one using the Momento CLI

Examples

Ready to dive right in? Just check out the examples directory for complete, working examples of how to use the SDK.

Installation

Use npm to install Momento:

npm install @gomomento/sdk

Usage

Checkout our examples directory for complete examples of how to use the SDK.

Here is a quickstart you can use in your own project:

import {
  CacheGet,
  ListCaches,
  CreateCache,
  CacheSet,
  CacheDelete,
  LogLevel,
  LogFormat,
  SimpleCacheClient,
  EnvMomentoTokenProvider,
  Configurations,
  LoggerOptions,
} from '@gomomento/sdk';

const cacheName = 'cache';
const cacheKey = 'key';
const cacheValue = 'value';

const credentialsProvider = new EnvMomentoTokenProvider('MOMENTO_AUTH_TOKEN');

const loggerOptions: LoggerOptions = {
  level: LogLevel.INFO,
  format: LogFormat.JSON,
};

const defaultTtl = 60;
const momento = new SimpleCacheClient({
  configuration: Configurations.Laptop.latest(loggerOptions),
  credentialProvider: credentialsProvider,
  defaultTtlSeconds: defaultTtl,
});

const main = async () => {
  const createCacheResponse = await momento.createCache(cacheName);
  if (createCacheResponse instanceof CreateCache.AlreadyExists) {
    console.log('cache already exists');
  } else if (createCacheResponse instanceof CreateCache.Error) {
    throw createCacheResponse.innerException();
  }

  console.log('Listing caches:');
  let token: string | undefined;
  do {
    const listResponse = await momento.listCaches(token);
    if (listResponse instanceof ListCaches.Error) {
      console.log(`Error listing caches: ${listResponse.message()}`);
      break;
    } else if (listResponse instanceof ListCaches.Success) {
      listResponse.getCaches().forEach(cacheInfo => {
        console.log(`${cacheInfo.getName()}`);
      });
      token = listResponse.getNextToken();
    }
  } while (token !== undefined);

  const exampleTtlSeconds = 10;
  console.log(
    `Storing key=${cacheKey}, value=${cacheValue}, ttl=${exampleTtlSeconds}`
  );
  const setResponse = await momento.set(
    cacheName,
    cacheKey,
    cacheValue,
    exampleTtlSeconds
  );
  if (setResponse instanceof CacheSet.Success) {
    console.log(
      'Key stored successfully with value ' + setResponse.valueString()
    );
  } else if (setResponse instanceof CacheSet.Error) {
    console.log('Error setting key: ' + setResponse.message());
  }

  const getResponse = await momento.get(cacheName, cacheKey);
  if (getResponse instanceof CacheGet.Hit) {
    console.log(`cache hit: ${String(getResponse.valueString())}`);
  } else if (getResponse instanceof CacheGet.Miss) {
    console.log('cache miss');
  } else if (getResponse instanceof CacheGet.Error) {
    console.log(`Error: ${getResponse.message()}`);
  }

  const deleteResponse = await momento.delete(cacheName, cacheKey);
  if (deleteResponse instanceof CacheDelete.Error) {
    console.log(`Error deleting cache key: ${deleteResponse.message()}`);
  } else if (deleteResponse instanceof CacheDelete.Success) {
    console.log('Deleted key from cache');
  }
};

main()
  .then(() => {
    console.log('success!!');
  })
  .catch((e: Error) => {
    console.error(`failed to get from cache ${e.message}`);
    throw e;
  });

Momento also supports storing pure bytes,

const key = new Uint8Array([109, 111, 109, 101, 110, 116, 111]);
const value = new Uint8Array([
  109, 111, 109, 101, 110, 116, 111, 32, 105, 115, 32, 97, 119, 101, 115, 111,
  109, 101, 33, 33, 33,
]);
const setResponse = await momento.set('cache', key, value, 50);
const getResponse = await momento.get('cache', key);

Handling cache misses,

const getResponse = await cache.get('cache', 'non-existent key');
if (getResponse instanceof CacheGet.Miss) {
  console.log('cache miss');
}

And storing files.

const buffer = fs.readFileSync('./file.txt');
const filebytes = Uint8Array.from(buffer);
const cacheKey = 'key';
const cacheName = 'my example cache';

// store file in cache
const setResponse = await momento.set(cacheName, cacheKey, filebytes);

// retrieve file from cache
const getResponse = await momento.get(cacheName, cacheKey);

// write file to disk
if (getResponse instanceof CacheGet.Hit) {
  fs.writeFileSync('./file-from-cache.txt', Buffer.from(getResponse.valueUint8Array()));
}

Error Handling

Errors that occur in calls to SimpleCacheClient methods are surfaced to developers as part of the return values of the calls, as opposed to by throwing exceptions. This makes them more visible, and allows your IDE to be more helpful in ensuring that you've handled the ones you care about. (For more on our philosophy about this, see our blog post on why Exceptions are bugs. And send us any feedback you have!)

The preferred way of interpreting the return values from SimpleCacheClient methods is using instanceof to match and handle the specific response type. Here's a quick example:

const getResponse = await client.get(CACHE_NAME, KEY);
if (getResponse instanceof CacheGet.Hit) {
    console.log(`Looked up value: ${getResponse.valueString()}`);
} else {
    // you can handle other cases via pattern matching in "else if" blocks, or a default case
    // via an `else` block.  For each conditional, your IDE should be able to give you code
    // completion indicating the possible types; in this case, `CacheGet.Miss` and `CacheGet.Error`.
}

Using this approach, you get a type-safe response object in the case of a cache hit. But if the cache read results in a Miss or an error, you'll also get a type-safe object that you can use to get more info about what happened.

In cases where you get an error response, it will always include an ErrorCode that you can use to check the error type:

const getResponse = await client.get(CACHE_NAME, KEY);
if (getResponse instanceof CacheGet.Error) {
    if (getResponse.errorCode() == MomentoErrorCode.TIMEOUT_ERROR) {
       // this would represent a client-side timeout, and you could fall back to your original data source
    }
}

Note that, outside of SimpleCacheClient responses, exceptions can occur and should be handled as usual. For example, trying to instantiate a SimpleCacheClient with an invalid authentication token will result in an IllegalArgumentException being thrown.

Tuning

TODO: Coming Soon


For more info, visit our website at https://gomomento.com!