reym
Sync

SDK

Freym Sync SDK documentation

Installation

To install the SDK, run the following command:

npm i --save @fraym/sync
go get -u github.com/freym/freym-api/go

Configuration

Using ENV Variables

You can configure the SDK by setting the following environment variables:

Variable NameDefaultDescription
SYNC_CLIENT_ADDRESSAddress of the sync service
SYNC_CLIENT_APP_PREFIX""A prefix that identifies the application aquiring the lock

Then use the configuration like this:

import { getEnvConfig } from "@fraym/sync";

...

const config = getEnvConfig();
import (
    "github.com/Becklyn/go-wire-core/env"
    "github.com/fraym/freym-api/go/sync/config"
)

...

_ = env.New() // this reads your environment variables from a `.env` or `.env.local` file
conf := config.NewEnvConfig()

Using Code Configuration

import { useConfigDefaults } from "@fraym/sync";

...

const config = useConfigDefaults({
    serverAddress: "my.sync.service",
    appPrefix: "my-app",
});
import "github.com/fraym/freym-api/go/sync/config"

...

conf := config.NewDefaultConfig()
conf.Address = "my.sync.service"
conf.AppPrefix = "my-app"

Usage

Initialize the Client

import { newClient } from "@fraym/sync";

...

const client = await newClient({
    serverAddress: "my.sync.service",
    appPrefix: "my-app",
});

...

// use your client here

... 

// this will gracefully end the connection to the sync service 
// ensuring all locks that are still held are released without needing to wait for the lease timeout
// call this before your service terminates
await client.stop();
import (
	"github.com/fraym/freym-api/go/sync"
	"github.com/fraym/golog"
)

logger := golog.NewZerologLogger()
client, err := sync.NewClient(logger, conf, func(cc grpc.ClientConnInterface) any {
    return &struct{}{}
})
if err != nil {
    panic(err)
}

// this will gracefully end the connection to the sync service 
// ensuring all locks that are still held are released without needing to wait for the lease timeout
// call this before your service terminates
defer client.Stop()

// use your client here

Parent Resource Locks

Use parent resource locks to ensure that only one process at a time can work on a resource group. No child resource within that parent resource can be processed while the parent resource lock is held.

await client.lock("tenant-id", "parent-resource");
// Do your work here
await client.unlock("tenant-id", "parent-resource");
if err := syncClient.Lock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
); err != nil {
    panic(err)
}
defer syncClient.Unlock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
)

// Do your work here

Parent Resource Read Locks

await client.rLock("tenant-id", "parent-resource");
// Do your work here
await client.rUnlock("tenant-id", "parent-resource");
if err := syncClient.RLock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
); err != nil {
    panic(err)
}
defer syncClient.RUnlock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
)

// Do your work here

Child Resource Locks

Use child resource locks to synchronize parallel processing of child resources within a parent resource.

await client.lock("tenant-id", "parent-resource", "child-resource");
// Do your work here
await client.unlock("tenant-id", "parent-resource", "child-resource");
if err := syncClient.Lock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
    "child-resource",
); err != nil {
    panic(err)
}
defer syncClient.Unlock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
    "child-resource",
)

// Do your work here

Child Resource Read Locks

await client.rLock("tenant-id", "parent-resource", "child-resource");
// Do your work here
await client.rUnlock("tenant-id", "parent-resource", "child-resource");
if err := syncClient.RLock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
    "child-resource",
); err != nil {
    panic(err)
}
defer syncClient.RUnlock(
    context.TODO(), 
    "tenant-id", 
    "parent-resource",
    "child-resource",
)

// Do your work here