Getting started with Google Cloud server less functions

Do you know how many lines of code you need to deploy a google cloud server less function?

Short Answer – 4

exports.helloWorld = (req, res) => {
  let message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

https://cloud.google.com/functions/docs/quickstart-nodejs

Wait, what’s a server less function?

Have you heard of micro services? This is like that but even smaller. What’s the smallest service you could possible deploy? a single function. Server less still uses a server, but the infrastructure is abstracted away by your cloud provider of choice. If no one is hitting your API, there’s no server running and costing you money. Cloud providers spin up an instance when needed as soon as something calls your function.

If you are interested in learning more, you should go to Severless Sydney on Saturday the 27th of August. Tickets are $69. https://sydney.serverlessdays.io

How do you integrate a server less function with a mySQL backend?

const mysql = require('mysql');
const connectionName =
process.env.INSTANCE_CONNECTION_NAME || 'boglogger:australia-southeast1:boglogger2';
const dbUser = process.env.SQL_USER || 'DEMOUSER';
const dbPassword = process.env.SQL_PASSWORD || 'DEMOPASSWORD';
const dbName = process.env.SQL_NAME || 'bog_logger';
const mysqlConfig = {
connectionLimit: 1,
user: dbUser,
password: dbPassword,
database: dbName,
};
if (process.env.NODE_ENV === 'production') {
mysqlConfig.socketPath = `/cloudsql/${connectionName}`;
}
// Connection pools reuse connections between invocations,
// and handle dropped or expired connections automatically.
let mysqlPool;
exports.logBog = (req, res) => {
// Initialize the pool lazily, in case SQL access isn't needed for this
// GCF instance. Doing so minimizes the number of active SQL connections,
// which helps keep your GCF instances under SQL connection limits.
if (!mysqlPool) {
mysqlPool = mysql.createPool(mysqlConfig);
}
mysqlPool.query('SELECT NOW() AS now', (err, results) => {
if (err) {
console.error(err);
res.status(500).send(err);
} else {
res.send(JSON.stringify(results));
}
});
mysqlPool.query('INSERT INTO bogs_logged(time, device_uuid, type, amount, floater) VALUES(NOW(), "e5c15033-42b3-487d-b6c8-17a1b592e9bd", 2, "S", TRUE)', (err, results) => {
if (err) {
console.error(err);
res.status(500).send(err);
} else {
res.send(JSON.stringify(results));
}
});
};

https://cloud.google.com/functions/docs/sql

How about getting JSON out of a request?

const escapeHtml = require('escape-html');
exports.helloContent = (req, res) => {
  let name;

  switch (req.get('content-type')) {
    // '{"name":"John"}'
    case 'application/json':
      name = req.body.name;
      break;
  }

  res.status(200).send(`Hello ${escapeHtml(name || 'World')}!`);
};

https://cloud.google.com/functions/docs/writing/http

Combining HTTP and MySQL

Now let’s combine the two, let’s build an API that logs your device ID and your poo type into a google cloud instance:

const escape = require('escape-html');
const mysql = require('mysql');
const connectionName =
process.env.INSTANCE_CONNECTION_NAME || 'boglogger:asia-northeast1:boglogger-prod';
const dbUser = process.env.SQL_USER || 'addBogs';
const dbPassword = process.env.SQL_PASSWORD || '';
const dbName = process.env.SQL_NAME || 'bog_logger';
const mysqlConfig = {
connectionLimit: 1,
user: dbUser,
password: dbPassword,
database: dbName,
};
if (process.env.NODE_ENV === 'production') {
mysqlConfig.socketPath = /cloudsql/${connectionName};
}
let mysqlPool;
exports.addBog = (req, res) => {
let device_id;
let type;
if (!mysqlPool) {
mysqlPool = mysql.createPool(mysqlConfig);
}
switch (req.get('content-type')) {
// '{"device_id":"123", "type": 2}'
case 'application/json':
device_id = req.body.device_id;
type = req.body.type;
break;
}
res.status(200).send(BogLogged ${escape(device_id || '123')}!);
mysqlPool.query(INSERT INTO bogs_logged(time, device_uuid, type) VALUES(NOW(), "${escape(device_id)}", ${escape(type)}), (err, results) => {
if (err) {
console.error(err);
res.status(500).send(err);
} else {
res.send(JSON.stringify(results));
}
});
};

https://github.com/BugHunterSam/BogLogger/blob/master/day2Stream21-07-2019/severlessAPIAddBogs.js

My API is in production if you hit this API with a POST Request

https://asia-northeast1-boglogger.cloudfunctions.net/addBogs

With JSON

{

"device_id":"123abc",

"type": 3

}

I will log your entry in a mySQL backend

When you deploy that function from above you will need a few packages in your dependencies in your package.json file:

{
"name": "sample-http",
"version": "0.0.1",
"dependencies": {
"mysql": "2.17.1",
"escape-html": "1.0.3"
}
}

If you want to run your own API, you will need to create a google cloud SQL instance and add a user. You can use these commands to create a table and user.

--create tables and insert some test data
CREATE TABLE bogs_logged(time DATETIME NOT NULL, device_uuid VARCHAR(36) NOT NULL, type INT(1));

--create addBogs user
CREATE USER 'addBogs'@'%' IDENTIFIED BY '********';
GRANT SELECT, INSERT ON bog_logger.bogs_logged TO 'addBogs'@'%';

https://github.com/BugHunterSam/BogLogger/blob/master/day2Stream21-07-2019/SQL-users-and-triggers.txt

What’s the point of all of this?

I now have a server less API in production for my mobile wearable app to track your poo. Next Steps is building the UI!

1 comment

Leave a Reply