Skip to content

Commit

Permalink
feat: Lens runtime config (sourcenetwork#2497)
Browse files Browse the repository at this point in the history
## Relevant issue(s)

Resolves sourcenetwork#2496 

## Description

This PR adds a lens runtime option. It also includes some cleanup and
additional tests.

## Tasks

- [x] I made sure the code is well commented, particularly
hard-to-understand areas.
- [x] I made sure the repository-held documentation is changed
accordingly.
- [x] I made sure the pull request title adheres to the conventional
commit style (the subset used in the project can be found in
[tools/configs/chglog/config.yml](tools/configs/chglog/config.yml)).
- [x] I made sure to discuss its limitations such as threats to
validity, vulnerability to mistake and misuse, robustness to
invalidation of assumptions, resource requirements, ...

## How has this been tested?

`make test`

Specify the platform(s) on which this was tested:
- MacOS
  • Loading branch information
nasdf authored Apr 8, 2024
1 parent 4811ba9 commit 2a63036
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 70 deletions.
73 changes: 73 additions & 0 deletions db/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2024 Democratized Data Foundation
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package db

import (
"context"

"github.com/lens-vm/lens/host-go/engine/module"
"github.com/sourcenetwork/immutable"

"github.com/sourcenetwork/defradb/acp"
"github.com/sourcenetwork/defradb/events"
)

const (
defaultMaxTxnRetries = 5
updateEventBufferSize = 100
)

// Option is a funtion that sets a config value on the db.
type Option func(*db)

// WithACP enables access control. If path is empty then acp runs in-memory.
func WithACP(path string) Option {
return func(db *db) {
var acpLocal acp.ACPLocal
acpLocal.Init(context.Background(), path)
db.acp = immutable.Some[acp.ACP](&acpLocal)
}
}

// WithACPInMemory enables access control in-memory.
func WithACPInMemory() Option { return WithACP("") }

// WithUpdateEvents enables the update events channel.
func WithUpdateEvents() Option {
return func(db *db) {
db.events = events.Events{
Updates: immutable.Some(events.New[events.Update](0, updateEventBufferSize)),
}
}
}

// WithMaxRetries sets the maximum number of retries per transaction.
func WithMaxRetries(num int) Option {
return func(db *db) {
db.maxTxnRetries = immutable.Some(num)
}
}

// WithLensPoolSize sets the maximum number of cached migrations instances to preserve per schema version.
//
// Will default to `5` if not set.
func WithLensPoolSize(size int) Option {
return func(db *db) {
db.lensPoolSize = immutable.Some(size)
}
}

// WithLensRuntime returns an option that sets the lens registry runtime.
func WithLensRuntime(runtime module.Runtime) Option {
return func(db *db) {
db.lensRuntime = immutable.Some(runtime)
}
}
55 changes: 55 additions & 0 deletions db/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2024 Democratized Data Foundation
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package db

import (
"testing"

"github.com/lens-vm/lens/host-go/runtimes/wasmtime"
"github.com/stretchr/testify/assert"
)

func TestWithACP(t *testing.T) {
d := &db{}
WithACP("test")(d)
assert.True(t, d.acp.HasValue())
}

func TestWithACPInMemory(t *testing.T) {
d := &db{}
WithACPInMemory()(d)
assert.True(t, d.acp.HasValue())
}

func TestWithUpdateEvents(t *testing.T) {
d := &db{}
WithUpdateEvents()(d)
assert.NotNil(t, d.events)
}

func TestWithMaxRetries(t *testing.T) {
d := &db{}
WithMaxRetries(10)(d)
assert.True(t, d.maxTxnRetries.HasValue())
assert.Equal(t, 10, d.maxTxnRetries.Value())
}

func TestWithLensPoolSize(t *testing.T) {
d := &db{}
WithLensPoolSize(10)(d)
assert.Equal(t, 10, d.lensPoolSize.Value())
}

func TestWithLensRuntime(t *testing.T) {
d := &db{}
WithLensRuntime(wasmtime.New())(d)
assert.NotNil(t, d.lensRuntime.Value())
}
65 changes: 10 additions & 55 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
blockstore "github.com/ipfs/boxo/blockstore"
ds "github.com/ipfs/go-datastore"
dsq "github.com/ipfs/go-datastore/query"
"github.com/lens-vm/lens/host-go/engine/module"
"github.com/sourcenetwork/corelog"
"github.com/sourcenetwork/immutable"

Expand All @@ -44,11 +45,6 @@ var (
_ client.Collection = (*collection)(nil)
)

const (
defaultMaxTxnRetries = 5
updateEventBufferSize = 100
)

// DB is the main interface for interacting with the
// DefraDB storage system.
type db struct {
Expand All @@ -59,17 +55,19 @@ type db struct {

events events.Events

parser core.Parser
parser core.Parser

// The maximum number of cached migrations instances to preserve per schema version.
lensPoolSize immutable.Option[int]
lensRuntime immutable.Option[module.Runtime]

lensRegistry client.LensRegistry

// The maximum number of retries per transaction.
maxTxnRetries immutable.Option[int]

// The maximum number of cached migrations instances to preserve per schema version.
lensPoolSize immutable.Option[int]

// The options used to init the database
options any
options []Option

// The ID of the last transaction created.
previousTxnID atomic.Uint64
Expand All @@ -78,46 +76,6 @@ type db struct {
acp immutable.Option[acp.ACP]
}

// Functional option type.
type Option func(*db)

// WithACP enables access control. If path is empty then acp runs in-memory.
func WithACP(path string) Option {
return func(db *db) {
var acpLocal acp.ACPLocal
acpLocal.Init(context.Background(), path)
db.acp = immutable.Some[acp.ACP](&acpLocal)
}
}

// WithACPInMemory enables access control in-memory.
func WithACPInMemory() Option { return WithACP("") }

// WithUpdateEvents enables the update events channel.
func WithUpdateEvents() Option {
return func(db *db) {
db.events = events.Events{
Updates: immutable.Some(events.New[events.Update](0, updateEventBufferSize)),
}
}
}

// WithMaxRetries sets the maximum number of retries per transaction.
func WithMaxRetries(num int) Option {
return func(db *db) {
db.maxTxnRetries = immutable.Some(num)
}
}

// WithLensPoolSize sets the maximum number of cached migrations instances to preserve per schema version.
//
// Will default to `5` if not set.
func WithLensPoolSize(num int) Option {
return func(db *db) {
db.lensPoolSize = immutable.Some(num)
}
}

// NewDB creates a new instance of the DB using the given options.
func NewDB(
ctx context.Context,
Expand Down Expand Up @@ -149,15 +107,12 @@ func newDB(

// apply options
for _, opt := range options {
if opt == nil {
continue
}
opt(db)
}

// lensPoolSize may be set by `options`, and because they are funcs on db
// lens options may be set by `WithLens` funcs, and because they are funcs on db
// we have to mutate `db` here to set the registry.
db.lensRegistry = lens.NewRegistry(db.lensPoolSize, db)
db.lensRegistry = lens.NewRegistry(db, db.lensPoolSize, db.lensRuntime)

err = db.initialize(ctx)
if err != nil {
Expand Down
36 changes: 21 additions & 15 deletions lens/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,24 +84,30 @@ const DefaultPoolSize int = 5
// NewRegistry instantiates a new registery.
//
// It will be of size 5 (per schema version) if a size is not provided.
func NewRegistry(lensPoolSize immutable.Option[int], db TxnSource) client.LensRegistry {
var size int
if lensPoolSize.HasValue() {
size = lensPoolSize.Value()
} else {
size = DefaultPoolSize
func NewRegistry(
db TxnSource,
poolSize immutable.Option[int],
runtime immutable.Option[module.Runtime],
) client.LensRegistry {
registry := &lensRegistry{
poolSize: DefaultPoolSize,
runtime: wasmtime.New(),
modulesByPath: map[string]module.Module{},
lensPoolsByCollectionID: map[uint32]*lensPool{},
reversedPoolsByCollectionID: map[uint32]*lensPool{},
txnCtxs: map[uint64]*txnContext{},
}

if poolSize.HasValue() {
registry.poolSize = poolSize.Value()
}
if runtime.HasValue() {
registry.runtime = runtime.Value()
}

return &implicitTxnLensRegistry{
db: db,
registry: &lensRegistry{
poolSize: size,
runtime: wasmtime.New(),
modulesByPath: map[string]module.Module{},
lensPoolsByCollectionID: map[uint32]*lensPool{},
reversedPoolsByCollectionID: map[uint32]*lensPool{},
txnCtxs: map[uint64]*txnContext{},
},
db: db,
registry: registry,
}
}

Expand Down

0 comments on commit 2a63036

Please sign in to comment.