OrientDB server function versioning

OrientDB server function versioning

Assign
Yang Jun
Date
‣
Status
Completed

What & Why

  • All javascript functions exist within OrientDB as OFunction rows or objects

What you will learn

  • be proficient with git; fork OpenEDR, make changes, Pull-Request...
  • be proficient with Visual Studio Code execution breakpoint stepping through

How

Extend existing export.sh

  • First thing first, understand the data-structure of OFunction such that we can represent ALL the server side javascript functions appropriately as individual files

YJ's Documentation

Overview of exportFunctions.js

Purpose of exportFunctions.js

exportFunctions.js is a script to export out all ODB server-side functions into functionsONLY.json.
All the functions listed here will be exported out.
All the functions listed here will be exported out.

Output of exportFunctions.js

As mentioned in the previous section, exportFunctions.js will generate a JSON file called functionsONLY.json containing all ODB functions. Let's take a look into functionsONLY.json to find out how the functions are being stored:
notion image
As shown in the screenshot above, each function is stored as an object in the array records. For each object i.e. function, it contains 8 name-value pairs:
  • @type
  • @version
  • @class
  • idempotent - Specifies whether the function performs idempotent queries or executes non-idempotent commands
  • code - Contains code of the function
  • name - Specifies the name of the function
  • language - Specifies the scripting language used by the function
  • parameters - Specifies the parameters of the function

Codes Explanation

Next, we will take a look into exportFunctions.js codes to understand how the script is able to export out the ODB functions into a JSON file.
notion image
Line 8: const fs = require("fs")
Explanation: Include the File System module using the require() method. The Node.js file system module allows you to work with the file system on your computer e.g. read files, create files, write files etc.
 
Line 9: const connectODB = require('../../common/orientdb').connectODB;
Explanation: To connect to ODB
 
Lines 11-30 i.e. exportFunctions()
This is a flow of how exportFunctions() work:
  1. Connect to ODB
  1. Create a variable called output of value '{"records":['
  1. Retrieve ALL data from OFunction and convert it into JSON format. This is then stored into variable results.
      • The JavaScript ODB server-side functions are stored in the special OFunction class.
      • Structure of OFunction class:
        • notion image
          As shown in the red box above, OFunction class has 8 properties.
      • Output of the query in Line 14:
        • notion image
          From the results of the query, we can see that it is returning all data for every entry in OFunction.
  1. For each element in array results, it gets parsed into variable line. I added console.log(line) after line 16 to see the value of variable line. This is a snippet of the output:
    1. notion image
      From the screenshot above, we can see that it is parsing one function at a time to variable line.
      For every function, the script will delete the field @rid as seen in line 17 of exportFunctions.js i.e. delete line["@rid"]. Lastly, it will convert variable line into JSON string and append it to variable output. Each JSON string that gets appended will be separated by a comma.
  1. After all JSON strings have been appended, "]}" is appended at the end of variable output.
  1. Write variable output to functionsONLY.json
 
Line 32: exportFunctions();
Explanation: Call exportFunctions()

Extend existing exportFunctions.js

Current version of exportFunctions.js will export out all ODB server-side JavaScript functions into a single JSON file. What we need to do is to modify the codes such that the functions are exported out as individual files.
I have a total of 52 ODB server-side JavaScript functions, meaning that there should be 52 JavaScript files after running the modified exportFunctions.js.
notion image

To-do list

  1. Export into JavaScript file per ODB function instead of JSON files (file name should match the ODB function name)
  1. Move parameter fields to the top as comments
  1. Replace \n in code field with actual newlines for IDE viewing

Modified exportFunction.js codes

/*** * This script exports every ODB server-side function into individual JavaScript file ***/ const fs = require("fs") const connectODB = require('../../common/orientdb').connectODB; const fields = ["@version","@class","idempotent","code","name","language","parameters"] async function exportFunctions(){ _session = await connectODB() var output = '{"records":['; let results = await _session.query("select @this.toJSON() from OFunction").all(); for(var i = 0; i < results.length; i++) { var line = JSON.parse(results[i]['@this.toJSON()']); delete line["@rid"] var output = '//@type\n' output += line["@type"]+'\n\n' for(var k = 0; k < fields.length; k++) { output += '//'+fields[k]+'\n' output += line[fields[k]]+'\n\n' } //console.log(output) fs.writeFile(line['name']+'.js', output, function(err) { if(err) { return console.log(err); } console.log("The file was saved!"); process.exit(); }); } } exportFunctions();

Codes Explanation

Line 7: const fields = ["@version","@class","idempotent","code","name","language","parameters"] Explanation: Create an array fields containing all parameters of class OFunction excluding @type.
 
Lines 16-17:
var output = '//@type\n' output += line["@type"]+'\n\n'
Explanation: Declare variable output and append //@type (so that parameter becomes a comment) before appending value of @type for the particular function.
 
Lines 18-21:
for(var k = 0; k < fields.length; k++) { output += '//'+fields[k]+'\n' output += line[fields[k]]+'\n\n' }
Explanation: For each parameter in array fields, append the parameter name as a comment before appending its value into variable output. Repeat until all parameters have been appended.
 
Line 23:
fs.writeFile(line['name']+'.js', output, function(err) {
Explanation: Write content of variable output into JavaScript file. Name of the JavaScript file is the function name.

Output of modified exportFunctions.js

Before running the script, I had 13 files in the directory.
notion image
After running the script, I now have 65 files in the directory.
notion image
65 - 13 = 52 newly added files. As shown in the screenshot, the script was able to export out every ODB server-side functions into separate JavaScript files.
Let's compare the way data is structured inside the exported files before and after modification.
This is an example of how function sizeofdb was structured in functionsONLY.json BEFORE modification:
notion image
AFTER modification, function sizeofdb is now stored in its own file called sizeofdb.js. This is how it looks like inside sizeofdb.js:
notion image
Parameter name is listed as a comment and the parameter value is listed right below the parameter name. \n inside parameter code has been replaced with actual newlines. The way it is structured makes it easy for developers to read or edit the values before making the changes in ODB web UI.

Jym's Review, Test & Integration

Slight refactoring

As explained to Yang Jun, I still need the original / existing exportFunctions.js that creates output files that are directly consumed during installation by Orientdb container's entrypoint script.
common/orientdb.js is an older version of common/odb.js, which I removed & refactored all scripts within exportScripts/.
notion image
Really satisfying to work with Yang Jun because our ideas can turn into good implementation. It worked nicely as shown above after slight refactoring. Switching to Github Desktop, we see:
notion image
So from a developer perspective, the improvement is we now can track changes in ODB functions that were once opaque to git.
The workflow does not change much, every time ODB functions or schema are updated, we still run export.sh, but the enhanced version will dump changes into a new folder odbFunctions. These scripts are not meant to be imported into ODB, but for git to help track changes.
🧠
Why? there are a few cases in the past that changes made started to break ODB (eg. unclose records & whatever exception). We need a way to track & understand how things break!

Other enhancement(s) to this enhancement

  • To delete all odbFunctions/*.js before export because we don't want "orphans" (eg. we decide to rename a function..)
  • I re-ordered to `const fields = ["@version","@class","idempotent","parameters","name","language","code"]` because from a readability standpoint, we want to know the parameters we use with this function upfront or earlier, rather at the end.

To-do

  • Implement & test the delete-before-export changes
  • Update GH master & dev exportScripts & common, still based on old way.
  • Merge these changes to GH master & dev (including the new script outputs for tracking)
Â