realglobe-Inc / sugos

A high-level RPC framework to make remote controlling super easy.
Apache License 2.0
9 stars 0 forks source link
oss sugos

<img src="assets/images/sugos-banner.png" alt="Title Banner" height="148" style="height:148px" />

Build Status npm Version JS Standard

A high-level RPC framework to make remote controlling super easy.

What you can do with SUGOS is:

  1. Declare a function on a client.
  2. Call the function from another client.

SUGOS magically connect two clients on remote networks, and provides pseudo function interface as if they are on the same environment.

<img src="assets/images/sugos-overview.png" alt="Overview" />

It also supports event driven architecture. You can emit or listen remote events in Node.js events style. This feature greatly helps you to build applications for IoT or Cloud Robotics.

Table of Contents

Requirements

<img src="assets/images/nodejs-banner.png" alt="banner" height="40" style="height:40px" /> <img src="assets/images/npm-banner.png" alt="banner" height="40" style="height:40px" />

Getting Started

3 steps to be getting started

  1. Setup SUGO-Hub
  2. Declare modules on SUGO-Actor
  3. Access to modules from SUGO-Caller

Setup SUGO-Hub

<img src="assets/images/sugo-hub-banner.png" alt="banner" height="40" style="height:40px" />

Setup a SUGO-Hub server for actors and callers.

#!/usr/bin/env node
/**
 * This is an example of SUGO-Hub
 * @see https://github.com/realglobe-Inc/sugo-hub
 */
'use strict'

const sugoHub = require('sugo-hub')

;(async () => {
  // Start sugo-hub server
  let hub = await sugoHub({}).listen(3000)
  console.log(`SUGO Hub started at port: ${hub.port}`)
}).catch((err) => console.error(err))

Declare modules on SUGO-Actor

<img src="assets/images/sugo-actor-banner.png" alt="banner" height="40" style="height:40px" />

Create a SUGO-Actor instance and declare modules. Then, connect to the hub server.

#!/usr/bin/env

/**
 * This is an example of SUGO-Actor
 * @see https://github.com/realglobe-Inc/sugo-actor
 */
'use strict'

const sugoActor = require('sugo-actor')
const { Module } = sugoActor

;(async () => {
  let actor = sugoActor({
    /** Host of hub to connect */
    hostname: 'localhost',
    port: 3000,
    /** Name to identify this actor on the hub */
    key: 'my-actor-01',
    /** Modules to provide */
    modules: {
      // Example of a simple call-return function module
      tableTennis: new Module({
        async ping (pong = 'default pong!') {
          /* ... */
          return `"${pong}" from actor!` // Return to the remote caller
        }
      }),
      // Load plugin module
      timeBomb: require('./example-time-bomb-module')({})
    }
  })
  await actor.connect() // Connect to the hub server
}).catch((err) => console.error(err))

Access to modules from SUGO-Caller

<img src="assets/images/sugo-caller-banner.png" alt="banner" height="40" style="height:40px" />

Create a SUGO-Caller instance and connect to the actor with key. Then get access to modules and call functions as you like.

#!/usr/bin/env

/**
 * This is an example of SUGO-Caller
 * @see https://github.com/realglobe-Inc/sugo-caller
 */
'use strict'

const sugoCaller = require('sugo-caller')
;(async () => {
  let caller = sugoCaller({
    // Host of hub to connect
    hostname: 'localhost',
    port: 3000
  })
  // Connect to an actor with key
  let actor01 = await caller.connect('my-actor-01')

  // Using call-return function
  {
    let tableTennis = actor01.get('tableTennis')
    let pong = await tableTennis.ping('hey!')
    console.log(pong) // -> `"hey!" from actor!`
  }

}).catch((err) => console.error(err))

Advanced Usage

Using Event-Emit Interface

On actors, each module provides EventEmitter interface like .on(ev, handler) and .emit(ev, data) functions.

/**
 * This is an example module
 */
'use strict'

const { Module } = require('sugo-actor')

class TimeBomb extends Module {
  // Example of event emitting function
  async countDown (count) {
    const s = this
    let abort = () => { count = -1 }
    s.on('abort', abort) // Listen to events from the caller
    while (count > 0) {
      count--
      s.emit('tick', { count }) // Emit an event to the caller
      await new Promise((resolve) =>
        setTimeout(() => resolve(), 1000)
      )
    }
    s.off('abort', abort) // Remove event listener
    return count === -1 ? 'hiss...' : 'booom!!!'
  }
}

function newTimeBomb (...args) {
  return new TimeBomb(...args)
}

module.exports = newTimeBomb // Pass factory method
#!/usr/bin/env

/**
 * This is an example of SUGO-Caller to use event emit
 */
'use strict'

const sugoCaller = require('sugo-caller')

;(async () => {
  let caller = sugoCaller({ /* ... */ })
  let actor01 = await caller.connect('my-actor-01')

  // Using event emitting interface
  {
    let timeBomb = actor01.get('timeBomb')
    let tick = (data) => console.log(`tick: ${data.count}`)
    timeBomb.on('tick', tick) // Add listener
    let booom = await timeBomb.countDown(10)
    console.log(booom)
    timeBomb.off('tick', tick) // Remove listener
  }
}).catch((err) => console.error(err))

Tutorials

API Docs

Related Packages

There are a bunch of related package and there are listed in sugos-index page

Contributors

License

This software is released under the Apache-2.0 License.

Links