Risen.JS

Risen.JS

  • Docs
  • Tutorial
  • API
  • Help

›Tutorial

Introduction

  • Quickstart
  • Overview
  • Philosophy
  • Security
  • Terminology

Tutorial

  • Setting Up
  • Initialise Project
  • Prime Service
  • Render Service
  • Configure Framework
  • See Results

API Reference

  • Constructor
  • Instance
  • Services
  • Global Methods
  • Data Structure
  • Codes

Define the "render" service

Let's now define the second service called render. This service will have one operation called renderPage and will receive requests from your browser (routed through Express).

We are going to get the list of prime numbers from the service instances of prime. So here we want to split and dispatch the work between four prime service instances meaning we are calculating the full list in parallel!

The prime services will calculate the list of prime numbers and sent their responses back to the render service which will then combine all the results. After this, the service will generate the HTML server-side then send the response back to your browser.

Create Folder

Create a new folder called services/render and cd into that folder:

mkdir -p services/render && cd services/render

Create File

Create the file which will contain the service you are going to initialize in the framework later:

touch index.jsx

Add Service Definitions

Paste the following code into the file you've just created. This is to make the React.JS server-side rendering work:

import React from "react";
import PropTypes from "prop-types";
import { renderToString } from "react-dom/server";
import { Layout, Breadcrumb, Tag } from "antd";

const { Content, Footer } = Layout;

// The number of "prime" services we are going to split the work into.
const numberOfProcesses = 4;

// This will allow us to split the work into smaller batches
const getIntervals = (max, nInt) => {
  if (max <= nInt) {
    return [[0, max]];
  }
  const c = Math.floor(max / nInt);
  const r = [];
  for (let i = 0; i <= max; i += c) {
    const a = i === 0 ? i : (i += 1);
    const b = i + c > max ? max : i + c;
    if (a < max) r.push([a, b]);
  }
  return r;
};

const PrimeNumberApp = ({ prime, listOfPrimes }) => (
  <html lang="en">
    <head>
      <title>{`Prime Numbers Up To ${prime}`}</title>
      <link
        rel="stylesheet"
        type="text/css"
        href="https://cdnjs.cloudflare.com/ajax/libs/antd/4.8.2/antd.min.css"
      />
    </head>
    <body>
      <Layout className="layout">
        <Content style={{ padding: "0 50px" }}>
          <Breadcrumb style={{ margin: "16px 0" }}>
            <Breadcrumb.Item>Home</Breadcrumb.Item>
            <Breadcrumb.Item>Prime Number Finder</Breadcrumb.Item>
            <Breadcrumb.Item>
              Numbers Up To
              {` ${prime}`}
            </Breadcrumb.Item>
          </Breadcrumb>
          <div style={{ background: "#fff", padding: 24, minHeight: 280 }}>
            <div
              style={{
                background: "#fff",
                padding: 24,
                minHeight: "calc(100vh - 170px)",
              }}
            >
              {listOfPrimes.map((number) => (
                <Tag style={{ marginBottom: "8px" }} key={number}>
                  {number}
                </Tag>
              ))}
            </div>
          </div>
        </Content>
        <Footer
          style={{
            textAlign: "center",
          }}
        >
          {`This page was rendered on the server by an instance of the
            "${process.env.name}" service. Instance ID: ${process.env.instanceId}`}
        </Footer>
      </Layout>
    </body>
  </html>
);

PrimeNumberApp.propTypes = {
  prime: PropTypes.number.isRequired,
  listOfPrimes: PropTypes.arrayOf(PropTypes.number).isRequired,
};

export default {
  renderPage: async ({ sendSuccess, data, request }) => {
    const prime = parseInt(data.body.prime, 10);
    const intervals = getIntervals(prime, numberOfProcesses);
    return Promise.all(
      intervals.map(([start, end]) => request({
        body: { start, end },
        destination: "prime",
        functionName: "getPrimeListFromRange",
      })),
    ).then((results) => {
      // Reduce the results from all the processes into one array
      const listOfPrimes = results.reduce(
        (primeList, result) => primeList.concat(result.response),
        [],
      );
      // Send back to the browser
      return sendSuccess({
        result: renderToString(<PrimeNumberApp listOfPrimes={listOfPrimes} prime={prime} />),
      });
    });
  },
};

Notice how we are using ES6+ in this example. This is possible because Risen.JS supports runtime babel transpilation of service definition files before they are initialized. This means you don't have to mess around with doing this yourself before executing the framework.

Back To Root

Back To Root:

cd ../..

Summary

The folder structure should have so far should look like this:

├── package.json
├── services
│   ├── prime
│   │   └── index.js
│   └── render
│       └── index.jsx
└── yarn.lock

Now we have two services and are ready to initialize our Risen.JS application. Let's do some configuration next...

← Prime ServiceConfigure Framework →
  • Create Folder
  • Create File
  • Add Service Definitions
  • Back To Root
  • Summary
Topics
QuickstartOverviewPhilosophySecurityTerminology
Community
Code RepositoryIssuesPull RequestsStack Overflow
Links
NPMBuild StatusLicence StatusDependenciesGitHub Repo stars
Facebook Open Source
Copyright © 2018 - 2021 David Makuni