rtd.pub Docs
rtd.pub Home
  • Intro
  • Overview
  • Quickstart
  • Integrations
    • About integrations
    • Writing a plugin
    • Plugins
      • NATS
      • Kafka
      • Demo data
      • Socket
      • Webhook
  • Further reading
Powered by GitBook
On this page
  • Implementation
  • Installation
  • Try it out
  • Wrap up
  1. Integrations

Writing a plugin

Let's write a trivial plugin in go

PreviousAbout integrationsNextPlugins

Last updated 5 days ago

Note that this document is written pre-release. Details are subject to change.

One of the key features of rtd.pub is the ability to use any language to implement your integration with Excel. Perhaps you have an existing system that you want to extend, or simply prefer writing code in a particular language.

We really want to avoid boilerplate and make it as easy as possible, so that you can focus on adding value... as a PHB may say.

To show how easy it is, we're going to build a trivial plugin that counts from 0 to 60. Amazing, right? Not really, but hopefully this will give you a taste for how easy it is to do far more meaningful things.

Implementation

Create a go module and in main.go import some modules. (Note that these will be available when rtd.pub is generally available.)

Create a struct with an embedded PluginServer which handles the communication between your plugin and rtd.pub.

package main

import 	
(
	"github.com/acornsoftuk/plugin"
	pb "github.com/acornsoftuk/plugin/protos"
	"github.com/sirupsen/logrus"
)

type CountingPlugin struct {
	plugin.PluginBase
}

Next, some hooks to handle plugin lifecycle.

func (p *CountingPlugin) Run(ctx context.Context) error {
	logrus.Infof("CountingPlugin started")
	return nil
}

func (p *CountingPlugin) Stop(context.Context) {
	logrus.Infof("CountingPlugin stopped")
}

We want our counter to start when a user adds a rtdPub.Sub call to a formula cell. Implementing Subscribe starts the subscription to a given piece of data, which will ultimately land back into that cell.

The Subscribe func expects the topic ID (assigned by Excel), subject and additional parameters. Most important is the setResult callback that ensures a new value is written to the correct topic.

Plugins must respect the context ctx passed by the runtime, and terminate when it is cancelled. This ensures that values cease to be produced when the subscribe cells are deleted.

func (p *CountingPlugin) Subscribe(ctx context.Context,
	tid int32,
	subj string,
	params []string,
	setResult plugin.SendFunc) error {
	go func() {
		i := 0
		for {
			select {
			case <-ctx.Done():
				return
			default:
				if err := setResult(i); err != nil {
					logrus.Error(err)
				}
				i++
				if i == 60 {
					return
				}
				time.Sleep(1 * time.Second)
			}
		}
	}()

	logrus.Infof("Demo plugin got subscribe: %v", tid)
	return nil
}

func (p *DemoPlugin) Unsubscribe(topicId int32) error {
	logrus.Infof("Demo plugin got unsubscribe: %v", topicId)
	return nil
}

Which brings us neatly on to unsubscribes. This is called when there are no more cells referencing the topic. You do not need to implement this.

func (p *DemoPlugin) Unsubscribe(topicId int32) error {
	logrus.Infof("Got unsubscribe: %v", req)
}

Remember a plugin is an executable. Not much more to do now, other than start the thing up.

func main() {
	plugin.Start(&CountingPlugin{})
}

And build it (for Windows)

GOOS=windows go build -o rtdpi-demo.exe

This should yield rtdpi-demo.exe

Installation

Move or copy the .exe to the plugins folder where you have installed rtd.pub.

Edit rtdpub.yaml to look similar to the below. This creates a connector, which is a reified instance of a plugin. This plugin does not have any configuration values, but if it did, these could be added to the properties map.

rtdpub:
  plugins:
    path: ./plugins
    connectors:
      tutorial:
        uses: demo
        properties: {}

Try it out

Start Excel and create a blank workbook.

Add a formula in any cell like =rtdPub.Sub("tutorial", "amazing")

Stand back in amazement as the value updates.

While this is happening add another, =rtdPub.Sub("tutorial", "amazing") and watch the two cells update in unison. You can fill up or down to reference the same data point in multiple places.

If things couldn't get any more exciting, add =rtdPub.Sub("tutorial", "another") and see a new, distinct counter start.

You can see it running in the below video.

Wrap up

Easy! Coming soon is an example for Python.

If you have any questions along the way, we are here to help.

Drop us an email.
Page cover image
Trivial counter RTD function, with content coming from a go plugin.