Skip to content

Technical overview

Luka Murn edited this page Jun 21, 2019 · 3 revisions

Table of Contents


Introduction

SciNote is primarily designed as a multi-tenant web application.

SciNote is developed in Ruby on Rails. It is a monolithic web application, following Ruby on Rails guidelines and best practices. Some other important technological aspects of the SciNote platform:

  • Back-end is following the Rails's MVC implementation.
  • Front-end comprises of .html.erb views, rendered using server-side rendering, and jQuery JavaScript code that often relies on AJAX calls to trigger dynamic actions to the server. Majority of JavaScript code is local to individual pages.
  • Data is stored within PostgreSQL, and all files are stored on either filesystem or Amazon S3.
  • Less is used for CSS pre-processing.
  • Webpack is used to bundle front-end assets (.js, scss/.css).
  • Puma is used as the web application server of choice.
  • Background worker is implemented using Delayed::Job gem.
  • See Gemfile for the list of used technologies.

Prerequisites

These are the minimal technical requirements required to install SciNote server on a computer:

  • 512+ MB of dedicated RAM, and a dual-core CPU,
  • OS that supports Docker (Mac, Windows or Linux),
  • Makefile (make),
  • Docker,
  • docker-compose.

As stated above, all major operating systems (Mac, Windows, Linux) support Docker. However, due to the nature of the Docker implementation, as well as the tooling required around SciNote (Makefile, docker-compose), it is strongly suggested to deploy SciNote on a Linux operating system.

Docker and containers

SciNote relies heavily on Docker containers to separate its individual processes & services.

The following separate containers are employed on a running SciNote server:

  1. Database data container (persistent) hosts all database engine files, and is placed by default into /var/lib/docker/volumes folder on the host system;
  2. Files container (persistent) stores all generated & uploaded files when SciNote is configured to use local filesystem for storage (PAPERCLIP_STORAGE is set to 'filesystem'); it is mapped to the public/system folder within the SciNote root folder;
  3. Database engine container (non-persistent) hosts the database engine process;
  4. Job worker container (non-persistent) hosts the background worker process;
  5. Web worker container (non-persistent) hosts the web application process.

SciNote can be setup to run in various ways, but the following schema provides the most common - default - way of how to setup the SciNote containers:

Generally, all parts of the system can be modified; PostgreSQL engine, as well as the database data, can also reside outside the Docker containers; similarily, load balancing could also be done on the containerized Puma server; due to the containerized nature of the setup, any container can be pulled out and hosted in a different manner.

Engines and modularity

To achieve a level of modularity/extensibility, SciNote introducec a concept of addons. Modularity in the sense that additional features can be bundled alongside SciNote core in the form of addons. An addon is simply a Rails engine that adds/modifies functionalities of SciNote core (like e.g. Wordpress plugins).

Addons can be used to introduce new, toggle-able functionalities into SciNote at build-time. Often, however, addons will want to have some stitching points with SciNote core, which inherently means that they require to modify some of the SciNote core codebase (e.g. addons inject some of their components into existing SciNote core codebase). This is achieved by using the following methods:

  • ActiveRecord models are modified using decorator pattern (using class_eval);
  • Controller-s are modified using decorator pattern (using class_eval);
  • .erb templates are modified using Ruby Gem called Deface;
  • JavaScript code is modified in different ways; but mostly, a new .js file is contained with the addon, and referenced from the injected .erb view.

On an architectural level, all addons are - inherently - dependant on SciNote core, but they can also be dependant on one another.

The addons are packaged alongside SciNote at a build/deployment time. This means that once the SciNote (actually, Rails server) starts, the addons are loaded alongside SciNote core, and further modification while the server is running are not possible. This is what is meant by build-time modularity:

+-----------------------------------------------+
|  SCINOTE                                      |
|                                               |
|   SciNote core      addon #1   addon #2   ... |
| +----------------++----------+----------+     |
| |    frontend    || frontend | frontend |     |
| |  __    __    __||  __    __|  __    __| ... |
| |_/  \__/  \__/  ||_/  \__/  |_/  \__/  |     |
| |    backend     || backend  | backend  |     |
| +----------------++----------|----------|     |
+-----------------------------------------------+

To add an addon to a SciNote deployment, the following basic steps need to be done:

  • Addon source code must be added as a folder under:

    <scinote_root_dir>/addons/<my_addon>
  • Inside Gemfile, following reference must be added:

    gem '<my_addon>', path: 'addons/<my_addon>'
  • (If neccesary) Add the following reference inside config/routes.rb:

    mount My::Addon::Engine => '/'
  • (If neccesary) Add the following reference inside app/assets/javascripts/application.js.erb:

    //= require my/addon
  • (If neccesary) Add the following reference inside app/assets/stylesheets/application.scss (starting comment):

     *= require my/addon/application

Of course, additional steps might need to be done (e.g. configuring the addon via the initializer, etc.).