X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=doc.go;fp=doc.go;h=038ee11a36acc779fbaa845a35f32c311d2aa84c;hb=ae7460ab662366115f6decc834a109bfa8985cc6;hp=0000000000000000000000000000000000000000;hpb=135580f96b31e8dd0ccd5695df877a7942b912ae;p=ric-plt%2Fsdlgo.git diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..038ee11 --- /dev/null +++ b/doc.go @@ -0,0 +1,135 @@ +/* + Copyright (c) 2019 AT&T Intellectual Property. + Copyright (c) 2018-2019 Nokia. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* +Package sdlgo provides a lightweight, high-speed interface for accessing shared data storage. + +Shared Data Layer (SDL) is a concept where applications can use and share data using a common +storage. The storage must be optimised for very high tranactional throughput and very low +latency. Sdlgo is a library which provides applications an API to read and write data +to a common storage using key-value paradigm. In addition to this, sdlgo provides an +event mechanism that can be used to notify listeners that data was changed. + +This SDL version assumes that the DBAAS service provided by O-RAN community is +working as a storage backend. + +Namespace + +A shared data layer connection is instantiated to a namespace and data is +always read and modified within the namespace. Namespace provides data isolation across clients. +Namespace instantiation happens when the sdlgo instance is created. +E.g. the following code sets the SDL instance to use "example" as a namespace + sdl := sdlgo.NewSdlInstance("example", sdlgo.NewDatabase()) +Applications can use several namespaces at the same time by creating several sdlgo instances. + +Database connection + +In addition to creating the SDL instance, application is responsible for creating the backend +database connection with NewDatabase() method. When the connection is created, sdlgo shall open a +tcp connection to backend database immediatelly. The resulting connection may be used with several +SDL instances if application needs to use several namespaces at a time. E.g. + connection := sdlgo.NewDatabase() + ns1 := sdlgo.NewSdlInstance("ns1", connection) + ns2 := sdlgo.NewSdlInstance("ns2", connection) +For the backend database connection a circuit breaker design is used. If the connection fails, +an error is returned immediatelly to application. Restoration of the connection happens +automatically by SDL and application should retry the operation again after a while. + +Database service is discovered by using environment variables DBAAS_SERVICE_HOST and +DBAAS_SERVICE_PORT. If not set, localhost and port 6379 are used by default. + +Keys and data + +Clients save key-value pairs. Keys are allways strings. The types of the values must be of a basic +type, i.e. string, integer or byte array or slice. This means that the internal structures, like +protobufs or JSON objects, must be serialised to a byte array or slice before passing it to SDL. +Clients are responsible for managing the keys within a namespace. + +Some examples on how to set the data using different kind of input parameters: + +Basic usage, keys and values are given as own parameters (with mixed data types) + err := s.Set("key1", "value1", "key2", 2) + +Keys and values inside a slice (again with mixed types, thus empty interface used as a type) + exampleSlice := []interface{"key1", "value1", "key2", 2} + err := s.Set(exampleSlice) + +Data stored to a byte array + data := make([]byte), 3 + data[0] = 1 + data[1] = 2 + data[2] = 3 + s.Set("key", data) + +Keys and values stored into a map (byte array "data" used from previous example) + mapData := map[string]interface{ + "key1" : "data", + "key2" : 2, + "key3" : data, + } + +When data is read from SDL storage, a map is returned where the requested key works as map key. +If the key was not found, the value for the given key is nil. It is possible to request several +key with one Get() call. + +Groups + +SDL groups are unordered collections of members where each member is unique. Using the SDL API +it is possible to add/remove members from a group, remove the whole group or do queries like the +size of a group and if member belongs to a group. Like key-value storage, groups are per namespace. + +Events + +Events are a publish-subscribe pattern to indicate interested parties that there has been a change +in data. Delivery of the events are not guaranteed. In SDL, events are happening via channels and +channels are per namespace. It is possible to publish several kinds of events through one channel. + +In order to publish changes to SDL data, the publisher need to call an API function that supports +publishing. E.g. + err := sdl.SetAndPublish([]string{"channel1", "event1", "channel2", "event2"}, "key", "value") +This example will publish event1 to channel1 and event2 in channel2 after writing the data. + +When subscribing the channels, the application needs to first create an SDL instance for the desired +namespace. The subscription happens using the SubscribeChannel() API function. The parameters for +the function takes a callback function and one or many channels to be subscribed. When an event is +received for the given channel, the given callback function shall be called with one or many events. +It is possible to make several subscriptions for different channels using different callback +functions if different kind of handling is required. + + sdl := sdlgo.NewSdlInstance("namespace", sdlgo.NewDatabase()) + + cb1 := func(channel string, event ...string) { + fmt.Printf("cb1: Received %s from channel %s\n", event, channel) + } + + cb2 := func(channel string, event ...string) { + fmt.Printf("cb2: Received %s from channel %s\n", event, channel) + } + + sdl.SubscribeChannel(cb1, "channel1", "channel2") + sdl.SubscribeChannel(cb2, "channel3") + +This example subscribes three channels from "namespace" and assigns cb1 for channel1 and channel2 +whereas channel3 is assigned to cb2. + +The callbacks are called from a context of a goroutine that is listening for the events. When +application receives events, the preferred way to do the required processing of an event (e.g. read +from SDL) is to do it in another context, e.g. by triggering applications own goroutine using Go +channels. By doing like this, blocking the receive routine and possibly loosing events, can be +avoided. +*/ +package sdlgo