Sails-ArangoJs

Sails-ArangoJs

  • Docs
  • API

›Going Native

Getting Started

  • Installation
  • Creating Models
  • Testing

CRUD API

  • let
  • create
  • createEach
  • update
  • updateOne
  • upsert
  • find
  • findOne
  • sum
  • avg
  • destroy
  • count
  • aggregate
  • sample
  • findNear
  • findWithCount

Graph & Transactions

  • Implementing transacations
  • Graph

Going Native

  • Native Methods
  • Foxx Services

Foxx Services

Foxx services are very powerful in ArangoDb. The allow you to implement custom APIs inside the database. you can read mote about foxx service here

In sails-arangodb foxx services can be installed at runtime and called from transactions created inside the sails application.

Creating a basic foxx service

In this example we shall create a service for posting transactions to a third party API endpoint say for marketing.

create a foxx folder inside your sails application's controllers folder.

you can organize multiple services in folders.

create a marketing folder inside the foxx folder. While there, create a manifest.json file. The full process in creating foxx services is well documented here

manifest.json

{
  "name": "marketing",
  "engines": {
    "arangodb": "^3.0.0"
  },

  "main": "index.js",
  "scripts": {
    "setup": "scripts/setup.js",
    "postEntry": "scripts/post-entry.js"
  }
}

index.js

The index.js file can be used to allow get and post requests in a service. You may never need to use this feature and it can easily be disabled


'use strict';
const createRouter = require('@arangodb/foxx/router');
const joi = require('joi');

const router = createRouter();

module.context.use(router);

router
.get('/someroute', (req, res) => {
// const params = req.queryParams || {};

    try {
      const entry = {some: 'data' };
      res.send(entry);
    } catch (error) {
      res.send(error);
    }

})
.response(joi.object().required(), 'return some data')
.summary('some data service')
.description('Service to get some data from arango server');


setup.js

'use strict';

const db = require('@arangodb').db;
const queues = require('@arangodb/foxx/queues');

queues.create('api-queue');

if (!db._collection('marketing')) {
  db._createDocumentCollection('marketing');
}

post-entry.js

'use strict';
// const db = require('@arangodb').db;
const Joi = require('joi');
const request = require('@arangodb/request');

const schema = Joi.object({
  Url: Joi.string().required(),
  Params: Joi.object().required(),
});

function validate(params) {
  const validate = schema.validate(params, { allowUnknown: true });
  if (validate.error) {
    throw `PARAMS_VALIDATION_ERROR ${validate.error}`;
  }
}

const { argv } = module.context;
const params = Object.assign({}, argv[0]);
let response;
try {
  validate(params);

  response = request({
    method: 'post',
    url:
      process.env.NODE_ENV === 'production'
        ? `https://marketing.endpoint.com/api${params.Url}`
        : `http://127.0.0.1:1556/api${params.Url}`,
    headers: { apikey: process.env.MARKETING_API_KEY },
    form: params.Params,
  });

  if (response.status !== 200) {
    throw new Error(`Error posting ${JSON.stringify(response)}`);
  }
  // You may want to save

  db.marketing.save(params)
} catch (error) {
  throw error;
}

module.exports = response;


installing the service

The service folder has to be zipped. zip -vr api/foxx/marketing.zip api/foxx/marketing A service function can be created to run when sails lifts.

loadFoxxServices: async () => {
    try {
      const { dbConnection } = sails.getDatastore().manager;

      let services = await dbConnection.listServices();
      services = services.map((service) => service.mount);



      if (!services.includes('/marketing')) {
        const source = fs.createReadStream(
          path.join(__dirname, '../foxx/marketing.zip')
        );
        await dbConnection.installService(`/marketing`, source);
      } else {
        const source = fs.readFileSync(
          path.join(__dirname, '../foxx/marketing.zip')
        );
        await dbConnection.replaceService('/marketing', source);
      }

    } catch (error) {
      throw error
    }
  },

Using the service in a transaction

The service can be used either by http requests or by creating queues

an example using queues

 const apiQueue = queues.get('api-queue');

    const Params = {
      // ...created params object
    };

    apiQueue.push(
      { mount: '/marketing', name: 'postEntry' },
      {
        Url: '/marketing/end/point',
        Params,
      },
      {
        delayUntil: Date.now() + 1000,
        backOff: (failTimes) => failTimes * 1000,
        maxFailures: 100,
        // repeatTimes: Infinity,
        // repeatUntil => Date Timestamp,
        // repeatDelay: 500, //Milisoconds
        // success: ()=>{},
        // failure: ()=>{}
      }
    );

an example using foxx request

 const transaction = await Transaction({
        action: function (params) {
          const response = request({
            method: 'post',
            url: `/_db/${db._name()}/_api/foxx/scripts/postEntry`,
            qs: {
              mount: '/marketing',
            },
            body: {
              Url: params.Url,
              params.Params,
            },
            json: true,
          });

          const entry = response.json;

          if (!entry._key) {
            throw `${entry.errorMessage || 'Error'}`;
          }
          return entry;
        },

        writes: [],
        params: {
            Url: '/marketing/end/point',
        Params: {
          // ... the params you want to pass
        }
        },
      });

Environment Variables

You notice the use of environment variables. This is important for security and sharing variables between server and the db application.

The example below uses ubuntu server

in /etc/init.d/arangodb3 add the following at the top. (Change the directory to your environment variables source file.)


if [ -r ~/.profile ]; then
   source ~/.profile
fi

If the method does not work. You can edit /lib/systemd/system/arangodb3.service. This is a systemd.service file. Add EnvironmentFile=/etc/env

Make sure you proceed to create the file to look like this.

FOO="BAR"

Finaly, restart ArangoDb.

type the following command source ~/.profile and then restart the arangodb service

on mac development environment, edit cat /Applications/ArangoDB3-CLI.app/Contents/MacOS/ArangoDB3-CLI and add your env variables source files

#!/bin/bash
WD=$(dirname "$0")
# We are in Contents/MacOS. However everything is located under Contents/Resources
ROOTDIR=$(cd "$WD" && cd "../Resources" && pwd)
# create start script


source ~/.bash_profile

← Native Methods
  • Creating a basic foxx service
    • manifest.json
    • index.js
    • setup.js
    • post-entry.js
  • installing the service
    • Using the service in a transaction
  • Environment Variables
Sails-ArangoJs
Docs
Getting StartedAPI Reference
Community
User ShowcaseStack OverflowTwitter
More
BlogGitHub
Cloudhub Developer Community
Copyright © 2022 Cloud Hub Limited