Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

Latest commit

 

History

History
144 lines (117 loc) · 5.81 KB

File metadata and controls

144 lines (117 loc) · 5.81 KB

⛔ DEPRECATED ⛔

Since Apollo Server v4 it's recommend to use Keyv as a database adapter for cache and as Keyv improved support for cache compression, this project is no longer needed and will not be maintained anymore.

Instead I recommend using:

import { KeyvAdapter } from '@apollo/utils.keyvadapter';
import KeyvBrotli from '@keyv/compress-brotli';

import Keyv from 'keyv';
import zlib from 'zlib';

const keyv = new Keyv(process.env.REDIS_HOST, {
  ...
  compression: new KeyvBrotli({
    compressOptions: {
      params: {
        [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
        [zlib.constants.BROTLI_PARAM_QUALITY]: 3,
      },
    },
  }),
  ...
});

const server = new ApolloServer<ApolloContext>({
  ...
  cache: new KeyvAdapter(keyv, { disableBatchReads: true }),
  ...
});

SnappyCacheWrapper

No Maintenance Intended Tests CodeQL npm version npm downloads

This package exports an implementation of KeyValueCache that allows wrapping any other Apollo KeyValueCache implementation with an configurable Brooooooklyn/snappy compression layer. Its main goal is to limit the amount of memory used by the caching environment and at the same time the amount of data being in-transit from and to the caching environment.

Note: Snappy module has recently moved from hands to hands. Originally it was maintained by kesla/node-snappy who was unable to spend more time on it, so Brooooooklyn/snappy took over.

Usage

const { RedisCache } = require('apollo-server-cache-redis');
const { SnappyCacheWrapper } = require('apollo-server-snappy-cache-wrapper');

const redisCache = new RedisCache({
  host: 'redis-server',
});

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: new SnappyCacheWrapper(redisCache, {
    minimumCompressionSize: 262144,
  }),
  dataSources: () => ({
    moviesAPI: new MoviesAPI(),
  }),
});

Options

  • minimumCompressionSize (default: 262144) - defines minimal length of the data string, after exceeding which data proxied to wrapped cache are compressed by Snappy before being passed forward.

Debug

For better performance monitor of SnappyCacheWrapper module in your app, run your app with DEBUG env.

To get all debug messages from all modules:

DEBUG=* npm run start

To get debug messages only from snappy-wrapper module:

DEBUG=snappy-wrapper npm run start

Troubleshooting

invalid ELF header

One of the issues you can encounter when using kesla/node-snappy in your projects is invalid ELF header error. From my experience it's happening when you're building your package (including node_modules) on one operating system and try use it on a different operating system, ie. deploying Serverless app into AWS linux-based Lambda environment from a macOS-based machine.

Example error message:

2021-03-14T13:39:14.674Z	undefined	ERROR	Uncaught Exception 	
{
    "errorType": "Error",
    "errorMessage": "/var/task/node_modules/snappy/build/Release/binding.node: invalid ELF header",
    "stack": [
        "Error: /var/task/node_modules/snappy/build/Release/binding.node: invalid ELF header",
        "    at Object.Module._extensions..node (internal/modules/cjs/loader.js:1057:18)",
        "    at Module.load (internal/modules/cjs/loader.js:863:32)",
        "    at Function.Module._load (internal/modules/cjs/loader.js:708:14)",
        "    at Module.require (internal/modules/cjs/loader.js:887:19)",
        "    at require (internal/modules/cjs/helpers.js:74:18)",
        "    at bindings (/var/task/node_modules/bindings/bindings.js:112:48)",
        "    at Object.<anonymous> (/var/task/node_modules/snappy/snappy.js:2:34)",
        "    at Module._compile (internal/modules/cjs/loader.js:999:30)",
        "    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)",
        "    at Module.load (internal/modules/cjs/loader.js:863:32)"
    ]
}

Solution?:

  • One of the ways for dealing with that issue in Serverless environment would be a solution proposed in here. It boils down to adding packagerOptions to the webpack section of your serverless.yml file:
custom:
  webpack:
    includeModules: true
    packagerOptions:
      scripts:
        - yarn add --ignore-platform --ignore-optional @napi-rs/snappy-linux-x64-gnu
  • Another approach would be to have a build script that starts and works in a Docker container, that uses the same operating system and configuration as the target platform. Deployment should happens inside of the Docker container as well.