5 Commits

Author SHA1 Message Date
Pijus Kamandulis
28e3c0c3d8 Rename 'MapDS' to 'JsonDS'; Added some docs 2025-03-14 22:40:12 +02:00
Pijus Kamandulis
97eea30c97 Use msgpack instead of gob; Added data persistance for badger data store 2025-03-13 23:59:07 +02:00
Pijus Kamandulis
5fe60d831a Pinned 3rd party Github Actions 2025-03-12 23:48:42 +02:00
Pijus Kamandulis
d309d99906 Update dependancies 2025-03-12 23:24:08 +02:00
Pijus Kamandulis
b2516eda9f Stability improvements 2025-03-12 22:00:30 +02:00
26 changed files with 178 additions and 140 deletions

View File

@@ -12,7 +12,7 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Cross-Compile with xgo - name: Cross-Compile with xgo
uses: crazy-max/ghaction-xgo@v3.1.0 uses: crazy-max/ghaction-xgo@e22d3c8b089adba750d5a74738b8e95d96f0c991 # v3.1.0
with: with:
xgo_version: latest xgo_version: latest
go_version: 1.24.0 go_version: 1.24.0

View File

@@ -24,7 +24,7 @@ jobs:
go-version: 1.24.0 go-version: 1.24.0
- name: Cross-Compile with xgo - name: Cross-Compile with xgo
uses: crazy-max/ghaction-xgo@v3.1.0 uses: crazy-max/ghaction-xgo@e22d3c8b089adba750d5a74738b8e95d96f0c991 # v3.1.0
with: with:
xgo_version: latest xgo_version: latest
go_version: 1.24.0 go_version: 1.24.0
@@ -44,7 +44,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5 uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811 # v5
with: with:
distribution: goreleaser distribution: goreleaser
version: ${{ env.GITHUB_REF_NAME }} version: ${{ env.GITHUB_REF_NAME }}

View File

@@ -86,6 +86,7 @@ To disable SSL and run Cosmium on HTTP instead, you can use the `-DisableTls` fl
- **-Persist**: Saves data to the given path on application exit (When `-InitialData` argument is not supplied, it will try to load data from path supplied in `-Persist`) - **-Persist**: Saves data to the given path on application exit (When `-InitialData` argument is not supplied, it will try to load data from path supplied in `-Persist`)
- **-Port**: Listen port (default 8081) - **-Port**: Listen port (default 8081)
- **-LogLevel**: Sets the logging level (one of: debug, info, error, silent) (default info) - **-LogLevel**: Sets the logging level (one of: debug, info, error, silent) (default info)
- **-DataStore**: Allows selecting [storage backend](#data-storage-backends) (default "json")
These arguments allow you to configure various aspects of Cosmium's behavior according to your requirements. These arguments allow you to configure various aspects of Cosmium's behavior according to your requirements.
@@ -99,6 +100,18 @@ All mentioned arguments can also be set using environment variables:
- **COSMIUM_PORT** for `-Port` - **COSMIUM_PORT** for `-Port`
- **COSMIUM_LOGLEVEL** for `-LogLevel` - **COSMIUM_LOGLEVEL** for `-LogLevel`
### Data Storage Backends
Cosmium supports multiple storage backends for saving, loading, and managing data at runtime.
| Backend | Storage Location | Write Behavior | Memory Usage | Supports Initial JSON Load |
|----------|--------------------------|--------------------------|----------------------|----------------------------|
| `json` (default) | JSON file on disk 📄 | On application exit ⏳ | 🛑 More than Badger | ✅ Yes |
| `badger` | BadgerDB database on disk ⚡ | Immediately on write 🚀 | ✅ Less than JSON | ❌ No |
The `badger` backend is generally recommended as it uses less memory and writes data to disk immediately. However, if you need to load initial data from a JSON file, use the `json` backend.
# License # License
This project is [MIT licensed](./LICENSE). This project is [MIT licensed](./LICENSE).

View File

@@ -16,7 +16,7 @@ const (
) )
const ( const (
DataStoreMap = "map" DataStoreJson = "json"
DataStoreBadger = "badger" DataStoreBadger = "badger"
) )
@@ -33,8 +33,8 @@ func ParseFlags() ServerConfig {
persistDataPath := flag.String("Persist", "", "Saves data to given path on application exit") persistDataPath := flag.String("Persist", "", "Saves data to given path on application exit")
logLevel := NewEnumValue("info", []string{"debug", "info", "error", "silent"}) logLevel := NewEnumValue("info", []string{"debug", "info", "error", "silent"})
flag.Var(logLevel, "LogLevel", fmt.Sprintf("Sets the logging level %s", logLevel.AllowedValuesList())) flag.Var(logLevel, "LogLevel", fmt.Sprintf("Sets the logging level %s", logLevel.AllowedValuesList()))
dataStore := NewEnumValue("map", []string{DataStoreMap, DataStoreBadger}) dataStore := NewEnumValue("json", []string{DataStoreJson, DataStoreBadger})
flag.Var(dataStore, "DataStore", fmt.Sprintf("Sets the data store %s, (badger is currently in the experimental phase)", dataStore.AllowedValuesList())) flag.Var(dataStore, "DataStore", fmt.Sprintf("Sets the data store %s", dataStore.AllowedValuesList()))
flag.Parse() flag.Parse()
setFlagsFromEnvironment() setFlagsFromEnvironment()
@@ -77,11 +77,22 @@ func (c *ServerConfig) PopulateCalculatedFields() {
logger.SetLogLevel(logger.LogLevelInfo) logger.SetLogLevel(logger.LogLevelInfo)
} }
if c.DataStore == DataStoreBadger && if c.PersistDataFilePath != "" {
(c.InitialDataFilePath != "" || c.PersistDataFilePath != "") { fileInfo, _ := os.Stat(c.PersistDataFilePath)
logger.ErrorLn("InitialData and Persist options are currently not supported with Badger data store") if c.DataStore == DataStoreJson && fileInfo.IsDir() {
c.InitialDataFilePath = "" logger.ErrorLn("--Persist cannot be a directory when using json data store")
c.PersistDataFilePath = "" os.Exit(1)
}
if c.DataStore == DataStoreBadger && !fileInfo.IsDir() {
logger.ErrorLn("--Persist must be a directory when using Badger data store")
os.Exit(1)
}
}
if c.DataStore == DataStoreBadger && c.InitialDataFilePath != "" {
logger.ErrorLn("InitialData option is currently not supported with Badger data store")
os.Exit(1)
} }
} }

View File

@@ -13,7 +13,7 @@ import (
) )
func Test_Collections(t *testing.T) { func Test_Collections(t *testing.T) {
presets := []testPreset{PresetMapStore, PresetBadgerStore} presets := []testPreset{PresetJsonStore, PresetBadgerStore}
setUp := func(ts *TestServer, client *azcosmos.Client) *azcosmos.DatabaseClient { setUp := func(ts *TestServer, client *azcosmos.Client) *azcosmos.DatabaseClient {
ts.DataStore.CreateDatabase(datastore.Database{ID: testDatabaseName}) ts.DataStore.CreateDatabase(datastore.Database{ID: testDatabaseName})

View File

@@ -10,7 +10,7 @@ import (
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/internal/datastore" "github.com/pikami/cosmium/internal/datastore"
badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore" badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore"
mapdatastore "github.com/pikami/cosmium/internal/datastore/map_datastore" jsondatastore "github.com/pikami/cosmium/internal/datastore/json_datastore"
"github.com/pikami/cosmium/internal/logger" "github.com/pikami/cosmium/internal/logger"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@@ -26,7 +26,7 @@ func getDefaultTestServerConfig() *config.ServerConfig {
AccountKey: config.DefaultAccountKey, AccountKey: config.DefaultAccountKey,
ExplorerPath: "/tmp/nothing", ExplorerPath: "/tmp/nothing",
ExplorerBaseUrlLocation: config.ExplorerBaseUrlLocation, ExplorerBaseUrlLocation: config.ExplorerBaseUrlLocation,
DataStore: "map", DataStore: "json",
} }
} }
@@ -34,9 +34,9 @@ func runTestServerCustomConfig(configuration *config.ServerConfig) *TestServer {
var dataStore datastore.DataStore var dataStore datastore.DataStore
switch configuration.DataStore { switch configuration.DataStore {
case config.DataStoreBadger: case config.DataStoreBadger:
dataStore = badgerdatastore.NewBadgerDataStore() dataStore = badgerdatastore.NewBadgerDataStore(badgerdatastore.BadgerDataStoreOptions{})
default: default:
dataStore = mapdatastore.NewMapDataStore(mapdatastore.MapDataStoreOptions{}) dataStore = jsondatastore.NewJsonDataStore(jsondatastore.JsonDataStoreOptions{})
} }
api := api.NewApiServer(dataStore, configuration) api := api.NewApiServer(dataStore, configuration)
@@ -71,7 +71,7 @@ type testFunc func(t *testing.T, ts *TestServer, cosmosClient *azcosmos.Client)
type testPreset string type testPreset string
const ( const (
PresetMapStore testPreset = "MapDS" PresetJsonStore testPreset = "JsonDS"
PresetBadgerStore testPreset = "BadgerDS" PresetBadgerStore testPreset = "BadgerDS"
) )
@@ -84,12 +84,13 @@ func runTestsWithPreset(t *testing.T, name string, testPreset testPreset, f test
switch testPreset { switch testPreset {
case PresetBadgerStore: case PresetBadgerStore:
serverConfig.DataStore = config.DataStoreBadger serverConfig.DataStore = config.DataStoreBadger
case PresetMapStore: case PresetJsonStore:
serverConfig.DataStore = config.DataStoreMap serverConfig.DataStore = config.DataStoreJson
} }
ts := runTestServerCustomConfig(serverConfig) ts := runTestServerCustomConfig(serverConfig)
defer ts.Server.Close() defer ts.Server.Close()
defer ts.DataStore.Close()
client, err := azcosmos.NewClientFromConnectionString( client, err := azcosmos.NewClientFromConnectionString(
fmt.Sprintf("AccountEndpoint=%s;AccountKey=%s", ts.URL, config.DefaultAccountKey), fmt.Sprintf("AccountEndpoint=%s;AccountKey=%s", ts.URL, config.DefaultAccountKey),

View File

@@ -13,7 +13,7 @@ import (
) )
func Test_Databases(t *testing.T) { func Test_Databases(t *testing.T) {
presets := []testPreset{PresetMapStore, PresetBadgerStore} presets := []testPreset{PresetJsonStore, PresetBadgerStore}
runTestsWithPresets(t, "Database Create", presets, func(t *testing.T, ts *TestServer, client *azcosmos.Client) { runTestsWithPresets(t, "Database Create", presets, func(t *testing.T, ts *TestServer, client *azcosmos.Client) {
t.Run("Should create database", func(t *testing.T) { t.Run("Should create database", func(t *testing.T) {

View File

@@ -81,7 +81,7 @@ func documents_InitializeDb(t *testing.T, ts *TestServer) *azcosmos.ContainerCli
} }
func Test_Documents(t *testing.T) { func Test_Documents(t *testing.T) {
presets := []testPreset{PresetMapStore, PresetBadgerStore} presets := []testPreset{PresetJsonStore, PresetBadgerStore}
runTestsWithPresets(t, "Test_Documents", presets, func(t *testing.T, ts *TestServer, client *azcosmos.Client) { runTestsWithPresets(t, "Test_Documents", presets, func(t *testing.T, ts *TestServer, client *azcosmos.Client) {
collectionClient := documents_InitializeDb(t, ts) collectionClient := documents_InitializeDb(t, ts)

View File

@@ -9,7 +9,8 @@ import (
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/internal/datastore" "github.com/pikami/cosmium/internal/datastore"
badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore" badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore"
mapdatastore "github.com/pikami/cosmium/internal/datastore/map_datastore" jsondatastore "github.com/pikami/cosmium/internal/datastore/json_datastore"
"github.com/pikami/cosmium/internal/logger"
) )
func main() { func main() {
@@ -18,12 +19,16 @@ func main() {
var dataStore datastore.DataStore var dataStore datastore.DataStore
switch configuration.DataStore { switch configuration.DataStore {
case config.DataStoreBadger: case config.DataStoreBadger:
dataStore = badgerdatastore.NewBadgerDataStore() dataStore = badgerdatastore.NewBadgerDataStore(badgerdatastore.BadgerDataStoreOptions{
PersistDataFilePath: configuration.PersistDataFilePath,
})
logger.InfoLn("Using Badger data store")
default: default:
dataStore = mapdatastore.NewMapDataStore(mapdatastore.MapDataStoreOptions{ dataStore = jsondatastore.NewJsonDataStore(jsondatastore.JsonDataStoreOptions{
InitialDataFilePath: configuration.InitialDataFilePath, InitialDataFilePath: configuration.InitialDataFilePath,
PersistDataFilePath: configuration.PersistDataFilePath, PersistDataFilePath: configuration.PersistDataFilePath,
}) })
logger.InfoLn("Using in-memory data store")
} }
server := api.NewApiServer(dataStore, &configuration) server := api.NewApiServer(dataStore, &configuration)

26
go.mod
View File

@@ -5,19 +5,20 @@ go 1.24.0
require ( require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.3.0
github.com/cosmiumdev/json-patch/v5 v5.9.3 github.com/cosmiumdev/json-patch/v5 v5.9.11
github.com/dgraph-io/badger/v4 v4.6.0 github.com/dgraph-io/badger/v4 v4.6.0
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa github.com/vmihailenco/msgpack/v5 v5.4.1
golang.org/x/exp v0.0.0-20250305212735-054e65f0b394
) )
require ( require (
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/bytedance/sonic v1.12.9 // indirect github.com/bytedance/sonic v1.13.1 // indirect
github.com/bytedance/sonic/loader v0.2.3 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.5 // indirect github.com/cloudwego/base64x v0.1.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
@@ -44,15 +45,16 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect github.com/ugorji/go/codec v1.2.12 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect
golang.org/x/arch v0.14.0 // indirect golang.org/x/arch v0.15.0 // indirect
golang.org/x/crypto v0.35.0 // indirect golang.org/x/crypto v0.36.0 // indirect
golang.org/x/net v0.35.0 // indirect golang.org/x/net v0.37.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.31.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.23.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

56
go.sum
View File

@@ -10,18 +10,18 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xP
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ= github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2 h1:kYRSnvJju5gYVyhkij+RTJ/VR6QIUaCfWeaFm2ycsjQ=
github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/AzureAD/microsoft-authentication-library-for-go v1.3.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/bytedance/sonic v1.12.9 h1:Od1BvK55NnewtGaJsTDeAOSnLVO2BTSLOe0+ooKokmQ= github.com/bytedance/sonic v1.13.1 h1:Jyd5CIvdFnkOWuKXr+wm4Nyk2h0yAFsr8ucJgEasO3g=
github.com/bytedance/sonic v1.12.9/go.mod h1:uVvFidNmlt9+wa31S1urfwwthTWteBgG0hWuoKAXTx8= github.com/bytedance/sonic v1.13.1/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.3 h1:yctD0Q3v2NOGfSWPLPvG2ggA2kV6TS6s4wioyEqssH0= github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/cosmiumdev/json-patch/v5 v5.9.3 h1:l+Og3+5edqV2NHDo58sz72eS733lbXVYP61seYK43Do= github.com/cosmiumdev/json-patch/v5 v5.9.11 h1:WD2Wqaz/vO987z2FFdqgkj15HgYZ/Y5TpqE3I4T/iOQ=
github.com/cosmiumdev/json-patch/v5 v5.9.3/go.mod h1:WzSTCdia0WrlZtjnL19P4RiwWtfdyArm/E7stgEeP5g= github.com/cosmiumdev/json-patch/v5 v5.9.11/go.mod h1:YPZmckmv4ZY+oxKIOjgq3sIudHVB6VEMcicCS9LtVLM=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -58,8 +58,8 @@ github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17w
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q= github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@@ -112,27 +112,31 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.15.0 h1:QtOrQd0bTUnhNVNndMpLHNWrDmYzZ2KDqSrEymqInZw=
golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.15.0/go.mod h1:JmwW7aLIoRUKgaTzhkiEFxvcEiQGyOg9BMonBJUS7EE=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -1,8 +1,6 @@
package badgerdatastore package badgerdatastore
import ( import (
"encoding/gob"
"github.com/dgraph-io/badger/v4" "github.com/dgraph-io/badger/v4"
"github.com/pikami/cosmium/internal/logger" "github.com/pikami/cosmium/internal/logger"
) )
@@ -11,10 +9,15 @@ type BadgerDataStore struct {
db *badger.DB db *badger.DB
} }
func NewBadgerDataStore() *BadgerDataStore { type BadgerDataStoreOptions struct {
gob.Register([]interface{}{}) PersistDataFilePath string
}
badgerOpts := badger.DefaultOptions("").WithInMemory(true) func NewBadgerDataStore(options BadgerDataStoreOptions) *BadgerDataStore {
badgerOpts := badger.DefaultOptions(options.PersistDataFilePath)
if options.PersistDataFilePath == "" {
badgerOpts = badgerOpts.WithInMemory(true)
}
db, err := badger.Open(badgerOpts) db, err := badger.Open(badgerOpts)
if err != nil { if err != nil {
@@ -28,6 +31,7 @@ func NewBadgerDataStore() *BadgerDataStore {
func (r *BadgerDataStore) Close() { func (r *BadgerDataStore) Close() {
r.db.Close() r.db.Close()
r.db = nil
} }
func (r *BadgerDataStore) DumpToJson() (string, error) { func (r *BadgerDataStore) DumpToJson() (string, error) {

View File

@@ -1,13 +1,11 @@
package badgerdatastore package badgerdatastore
import ( import (
"bytes"
"encoding/gob"
"github.com/dgraph-io/badger/v4" "github.com/dgraph-io/badger/v4"
"github.com/pikami/cosmium/internal/datastore" "github.com/pikami/cosmium/internal/datastore"
"github.com/pikami/cosmium/internal/logger" "github.com/pikami/cosmium/internal/logger"
"github.com/pikami/cosmium/internal/resourceid" "github.com/pikami/cosmium/internal/resourceid"
"github.com/vmihailenco/msgpack/v5"
) )
const ( const (
@@ -92,14 +90,13 @@ func insertKey(txn *badger.Txn, key string, value interface{}) datastore.DataSto
return datastore.Unknown return datastore.Unknown
} }
var buf bytes.Buffer buf, err := msgpack.Marshal(value)
err = gob.NewEncoder(&buf).Encode(value)
if err != nil { if err != nil {
logger.ErrorLn("Error while encoding value:", err) logger.ErrorLn("Error while encoding value:", err)
return datastore.Unknown return datastore.Unknown
} }
err = txn.Set([]byte(key), buf.Bytes()) err = txn.Set([]byte(key), buf)
if err != nil { if err != nil {
logger.ErrorLn("Error while setting key:", err) logger.ErrorLn("Error while setting key:", err)
return datastore.Unknown return datastore.Unknown
@@ -135,7 +132,7 @@ func getKey(txn *badger.Txn, key string, value interface{}) datastore.DataStoreS
return datastore.Unknown return datastore.Unknown
} }
err = gob.NewDecoder(bytes.NewReader(val)).Decode(value) err = msgpack.Unmarshal(val, &value)
if err != nil { if err != nil {
logger.ErrorLn("Error while decoding value:", err) logger.ErrorLn("Error while decoding value:", err)
return datastore.Unknown return datastore.Unknown
@@ -158,7 +155,7 @@ func keyExists(txn *badger.Txn, key string) (bool, error) {
} }
func listByPrefix[T any](db *badger.DB, prefix string) ([]T, datastore.DataStoreStatus) { func listByPrefix[T any](db *badger.DB, prefix string) ([]T, datastore.DataStoreStatus) {
var results []T results := make([]T, 0)
err := db.View(func(txn *badger.Txn) error { err := db.View(func(txn *badger.Txn) error {
opts := badger.DefaultIteratorOptions opts := badger.DefaultIteratorOptions

View File

@@ -1,12 +1,10 @@
package badgerdatastore package badgerdatastore
import ( import (
"bytes"
"encoding/gob"
"github.com/dgraph-io/badger/v4" "github.com/dgraph-io/badger/v4"
"github.com/pikami/cosmium/internal/datastore" "github.com/pikami/cosmium/internal/datastore"
"github.com/pikami/cosmium/internal/logger" "github.com/pikami/cosmium/internal/logger"
"github.com/vmihailenco/msgpack/v5"
) )
type BadgerDocumentIterator struct { type BadgerDocumentIterator struct {
@@ -43,7 +41,7 @@ func (i *BadgerDocumentIterator) Next() (datastore.Document, datastore.DataStore
} }
current := &datastore.Document{} current := &datastore.Document{}
err = gob.NewDecoder(bytes.NewReader(val)).Decode(current) err = msgpack.Unmarshal(val, &current)
if err != nil { if err != nil {
logger.ErrorLn("Error while decoding value:", err) logger.ErrorLn("Error while decoding value:", err)
return datastore.Document{}, datastore.Unknown return datastore.Document{}, datastore.Unknown

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import "github.com/pikami/cosmium/internal/datastore" import "github.com/pikami/cosmium/internal/datastore"

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -11,7 +11,7 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllCollections(databaseId string) ([]datastore.Collection, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllCollections(databaseId string) ([]datastore.Collection, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -22,7 +22,7 @@ func (r *MapDataStore) GetAllCollections(databaseId string) ([]datastore.Collect
return maps.Values(r.storeState.Collections[databaseId]), datastore.StatusOk return maps.Values(r.storeState.Collections[databaseId]), datastore.StatusOk
} }
func (r *MapDataStore) GetCollection(databaseId string, collectionId string) (datastore.Collection, datastore.DataStoreStatus) { func (r *JsonDataStore) GetCollection(databaseId string, collectionId string) (datastore.Collection, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -37,7 +37,7 @@ func (r *MapDataStore) GetCollection(databaseId string, collectionId string) (da
return r.storeState.Collections[databaseId][collectionId], datastore.StatusOk return r.storeState.Collections[databaseId][collectionId], datastore.StatusOk
} }
func (r *MapDataStore) DeleteCollection(databaseId string, collectionId string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteCollection(databaseId string, collectionId string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -58,7 +58,7 @@ func (r *MapDataStore) DeleteCollection(databaseId string, collectionId string)
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateCollection(databaseId string, newCollection datastore.Collection) (datastore.Collection, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateCollection(databaseId string, newCollection datastore.Collection) (datastore.Collection, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -10,14 +10,14 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllDatabases() ([]datastore.Database, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllDatabases() ([]datastore.Database, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
return maps.Values(r.storeState.Databases), datastore.StatusOk return maps.Values(r.storeState.Databases), datastore.StatusOk
} }
func (r *MapDataStore) GetDatabase(id string) (datastore.Database, datastore.DataStoreStatus) { func (r *JsonDataStore) GetDatabase(id string) (datastore.Database, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -28,7 +28,7 @@ func (r *MapDataStore) GetDatabase(id string) (datastore.Database, datastore.Dat
return datastore.Database{}, datastore.StatusNotFound return datastore.Database{}, datastore.StatusNotFound
} }
func (r *MapDataStore) DeleteDatabase(id string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteDatabase(id string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -46,7 +46,7 @@ func (r *MapDataStore) DeleteDatabase(id string) datastore.DataStoreStatus {
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateDatabase(newDatabase datastore.Database) (datastore.Database, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateDatabase(newDatabase datastore.Database) (datastore.Database, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -10,7 +10,7 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllDocuments(databaseId string, collectionId string) ([]datastore.Document, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllDocuments(databaseId string, collectionId string) ([]datastore.Document, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -25,7 +25,7 @@ func (r *MapDataStore) GetAllDocuments(databaseId string, collectionId string) (
return maps.Values(r.storeState.Documents[databaseId][collectionId]), datastore.StatusOk return maps.Values(r.storeState.Documents[databaseId][collectionId]), datastore.StatusOk
} }
func (r *MapDataStore) GetDocument(databaseId string, collectionId string, documentId string) (datastore.Document, datastore.DataStoreStatus) { func (r *JsonDataStore) GetDocument(databaseId string, collectionId string, documentId string) (datastore.Document, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -44,7 +44,7 @@ func (r *MapDataStore) GetDocument(databaseId string, collectionId string, docum
return r.storeState.Documents[databaseId][collectionId][documentId], datastore.StatusOk return r.storeState.Documents[databaseId][collectionId][documentId], datastore.StatusOk
} }
func (r *MapDataStore) DeleteDocument(databaseId string, collectionId string, documentId string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteDocument(databaseId string, collectionId string, documentId string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -65,7 +65,7 @@ func (r *MapDataStore) DeleteDocument(databaseId string, collectionId string, do
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateDocument(databaseId string, collectionId string, document map[string]interface{}) (datastore.Document, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateDocument(databaseId string, collectionId string, document map[string]interface{}) (datastore.Document, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -100,7 +100,7 @@ func (r *MapDataStore) CreateDocument(databaseId string, collectionId string, do
return document, datastore.StatusOk return document, datastore.StatusOk
} }
func (r *MapDataStore) GetDocumentIterator(databaseId string, collectionId string) (datastore.DocumentIterator, datastore.DataStoreStatus) { func (r *JsonDataStore) GetDocumentIterator(databaseId string, collectionId string) (datastore.DocumentIterator, datastore.DataStoreStatus) {
documents, status := r.GetAllDocuments(databaseId, collectionId) documents, status := r.GetAllDocuments(databaseId, collectionId)
if status != datastore.StatusOk { if status != datastore.StatusOk {
return nil, status return nil, status

View File

@@ -1,21 +1,21 @@
package mapdatastore package jsondatastore
import "github.com/pikami/cosmium/internal/datastore" import "github.com/pikami/cosmium/internal/datastore"
type MapDataStore struct { type JsonDataStore struct {
storeState State storeState State
initialDataFilePath string initialDataFilePath string
persistDataFilePath string persistDataFilePath string
} }
type MapDataStoreOptions struct { type JsonDataStoreOptions struct {
InitialDataFilePath string InitialDataFilePath string
PersistDataFilePath string PersistDataFilePath string
} }
func NewMapDataStore(options MapDataStoreOptions) *MapDataStore { func NewJsonDataStore(options JsonDataStoreOptions) *JsonDataStore {
dataStore := &MapDataStore{ dataStore := &JsonDataStore{
storeState: State{ storeState: State{
Databases: make(map[string]datastore.Database), Databases: make(map[string]datastore.Database),
Collections: make(map[string]map[string]datastore.Collection), Collections: make(map[string]map[string]datastore.Collection),

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -9,7 +9,7 @@ import (
) )
// I have no idea what this is tbh // I have no idea what this is tbh
func (r *MapDataStore) GetPartitionKeyRanges(databaseId string, collectionId string) ([]datastore.PartitionKeyRange, datastore.DataStoreStatus) { func (r *JsonDataStore) GetPartitionKeyRanges(databaseId string, collectionId string) ([]datastore.PartitionKeyRange, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"encoding/json" "encoding/json"
@@ -33,7 +33,7 @@ type State struct {
UserDefinedFunctions map[string]map[string]map[string]datastore.UserDefinedFunction `json:"udfs"` UserDefinedFunctions map[string]map[string]map[string]datastore.UserDefinedFunction `json:"udfs"`
} }
func (r *MapDataStore) InitializeDataStore() { func (r *JsonDataStore) InitializeDataStore() {
if r.initialDataFilePath != "" { if r.initialDataFilePath != "" {
r.LoadStateFS(r.initialDataFilePath) r.LoadStateFS(r.initialDataFilePath)
return return
@@ -55,7 +55,7 @@ func (r *MapDataStore) InitializeDataStore() {
} }
} }
func (r *MapDataStore) LoadStateFS(filePath string) { func (r *JsonDataStore) LoadStateFS(filePath string) {
data, err := os.ReadFile(filePath) data, err := os.ReadFile(filePath)
if err != nil { if err != nil {
log.Fatalf("Error reading state JSON file: %v", err) log.Fatalf("Error reading state JSON file: %v", err)
@@ -68,7 +68,7 @@ func (r *MapDataStore) LoadStateFS(filePath string) {
} }
} }
func (r *MapDataStore) LoadStateJSON(jsonData string) error { func (r *JsonDataStore) LoadStateJSON(jsonData string) error {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -94,7 +94,7 @@ func (r *MapDataStore) LoadStateJSON(jsonData string) error {
return nil return nil
} }
func (r *MapDataStore) SaveStateFS(filePath string) { func (r *JsonDataStore) SaveStateFS(filePath string) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -115,7 +115,7 @@ func (r *MapDataStore) SaveStateFS(filePath string) {
logger.Infof("User defined functions: %d\n", getLength(r.storeState.UserDefinedFunctions)) logger.Infof("User defined functions: %d\n", getLength(r.storeState.UserDefinedFunctions))
} }
func (r *MapDataStore) DumpToJson() (string, error) { func (r *JsonDataStore) DumpToJson() (string, error) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -129,7 +129,7 @@ func (r *MapDataStore) DumpToJson() (string, error) {
} }
func (r *MapDataStore) Close() { func (r *JsonDataStore) Close() {
if r.persistDataFilePath != "" { if r.persistDataFilePath != "" {
r.SaveStateFS(r.persistDataFilePath) r.SaveStateFS(r.persistDataFilePath)
} }
@@ -163,7 +163,7 @@ func getLength(v interface{}) int {
return count return count
} }
func (r *MapDataStore) ensureStoreStateNoNullReferences() { func (r *JsonDataStore) ensureStoreStateNoNullReferences() {
if r.storeState.Databases == nil { if r.storeState.Databases == nil {
r.storeState.Databases = make(map[string]datastore.Database) r.storeState.Databases = make(map[string]datastore.Database)
} }

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -10,14 +10,14 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllStoredProcedures(databaseId string, collectionId string) ([]datastore.StoredProcedure, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllStoredProcedures(databaseId string, collectionId string) ([]datastore.StoredProcedure, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
return maps.Values(r.storeState.StoredProcedures[databaseId][collectionId]), datastore.StatusOk return maps.Values(r.storeState.StoredProcedures[databaseId][collectionId]), datastore.StatusOk
} }
func (r *MapDataStore) GetStoredProcedure(databaseId string, collectionId string, spId string) (datastore.StoredProcedure, datastore.DataStoreStatus) { func (r *JsonDataStore) GetStoredProcedure(databaseId string, collectionId string, spId string) (datastore.StoredProcedure, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -36,7 +36,7 @@ func (r *MapDataStore) GetStoredProcedure(databaseId string, collectionId string
return datastore.StoredProcedure{}, datastore.StatusNotFound return datastore.StoredProcedure{}, datastore.StatusNotFound
} }
func (r *MapDataStore) DeleteStoredProcedure(databaseId string, collectionId string, spId string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteStoredProcedure(databaseId string, collectionId string, spId string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -57,7 +57,7 @@ func (r *MapDataStore) DeleteStoredProcedure(databaseId string, collectionId str
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateStoredProcedure(databaseId string, collectionId string, sp datastore.StoredProcedure) (datastore.StoredProcedure, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateStoredProcedure(databaseId string, collectionId string, sp datastore.StoredProcedure) (datastore.StoredProcedure, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -10,14 +10,14 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllTriggers(databaseId string, collectionId string) ([]datastore.Trigger, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllTriggers(databaseId string, collectionId string) ([]datastore.Trigger, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
return maps.Values(r.storeState.Triggers[databaseId][collectionId]), datastore.StatusOk return maps.Values(r.storeState.Triggers[databaseId][collectionId]), datastore.StatusOk
} }
func (r *MapDataStore) GetTrigger(databaseId string, collectionId string, triggerId string) (datastore.Trigger, datastore.DataStoreStatus) { func (r *JsonDataStore) GetTrigger(databaseId string, collectionId string, triggerId string) (datastore.Trigger, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -36,7 +36,7 @@ func (r *MapDataStore) GetTrigger(databaseId string, collectionId string, trigge
return datastore.Trigger{}, datastore.StatusNotFound return datastore.Trigger{}, datastore.StatusNotFound
} }
func (r *MapDataStore) DeleteTrigger(databaseId string, collectionId string, triggerId string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteTrigger(databaseId string, collectionId string, triggerId string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -57,7 +57,7 @@ func (r *MapDataStore) DeleteTrigger(databaseId string, collectionId string, tri
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateTrigger(databaseId string, collectionId string, trigger datastore.Trigger) (datastore.Trigger, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateTrigger(databaseId string, collectionId string, trigger datastore.Trigger) (datastore.Trigger, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()

View File

@@ -1,4 +1,4 @@
package mapdatastore package jsondatastore
import ( import (
"fmt" "fmt"
@@ -10,14 +10,14 @@ import (
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
) )
func (r *MapDataStore) GetAllUserDefinedFunctions(databaseId string, collectionId string) ([]datastore.UserDefinedFunction, datastore.DataStoreStatus) { func (r *JsonDataStore) GetAllUserDefinedFunctions(databaseId string, collectionId string) ([]datastore.UserDefinedFunction, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
return maps.Values(r.storeState.UserDefinedFunctions[databaseId][collectionId]), datastore.StatusOk return maps.Values(r.storeState.UserDefinedFunctions[databaseId][collectionId]), datastore.StatusOk
} }
func (r *MapDataStore) GetUserDefinedFunction(databaseId string, collectionId string, udfId string) (datastore.UserDefinedFunction, datastore.DataStoreStatus) { func (r *JsonDataStore) GetUserDefinedFunction(databaseId string, collectionId string, udfId string) (datastore.UserDefinedFunction, datastore.DataStoreStatus) {
r.storeState.RLock() r.storeState.RLock()
defer r.storeState.RUnlock() defer r.storeState.RUnlock()
@@ -36,7 +36,7 @@ func (r *MapDataStore) GetUserDefinedFunction(databaseId string, collectionId st
return datastore.UserDefinedFunction{}, datastore.StatusNotFound return datastore.UserDefinedFunction{}, datastore.StatusNotFound
} }
func (r *MapDataStore) DeleteUserDefinedFunction(databaseId string, collectionId string, udfId string) datastore.DataStoreStatus { func (r *JsonDataStore) DeleteUserDefinedFunction(databaseId string, collectionId string, udfId string) datastore.DataStoreStatus {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()
@@ -57,7 +57,7 @@ func (r *MapDataStore) DeleteUserDefinedFunction(databaseId string, collectionId
return datastore.StatusOk return datastore.StatusOk
} }
func (r *MapDataStore) CreateUserDefinedFunction(databaseId string, collectionId string, udf datastore.UserDefinedFunction) (datastore.UserDefinedFunction, datastore.DataStoreStatus) { func (r *JsonDataStore) CreateUserDefinedFunction(databaseId string, collectionId string, udf datastore.UserDefinedFunction) (datastore.UserDefinedFunction, datastore.DataStoreStatus) {
r.storeState.Lock() r.storeState.Lock()
defer r.storeState.Unlock() defer r.storeState.Unlock()

View File

@@ -20,14 +20,14 @@ var (
const ( const (
ResponseSuccess = 0 ResponseSuccess = 0
ResponseUnknown = 100 ResponseUnknown = 100
ResponseFailedToParseConfiguration = 101 ResponseFailedToParseConfiguration = 101
ResponseFailedToLoadState = 102 ResponseFailedToLoadState = 102
ResponseFailedToParseRequest = 103 ResponseFailedToParseRequest = 103
ResponseServerInstanceAlreadyExists = 104 ResponseServerInstanceAlreadyExists = 104
ResponseServerInstanceNotFound = 105 ResponseServerInstanceNotFound = 105
ResponseFailedToStartServer = 106 ResponseFailedToStartServer = 106
ResponseCurentDataStoreDoesNotSupportStateLoading = 107 ResponseCurrentDataStoreDoesNotSupportStateLoading = 107
ResponseDataStoreNotFound = 200 ResponseDataStoreNotFound = 200
ResponseDataStoreConflict = 201 ResponseDataStoreConflict = 201

View File

@@ -13,7 +13,7 @@ import (
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/internal/datastore" "github.com/pikami/cosmium/internal/datastore"
badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore" badgerdatastore "github.com/pikami/cosmium/internal/datastore/badger_datastore"
mapdatastore "github.com/pikami/cosmium/internal/datastore/map_datastore" jsondatastore "github.com/pikami/cosmium/internal/datastore/json_datastore"
) )
//export CreateServerInstance //export CreateServerInstance
@@ -37,9 +37,11 @@ func CreateServerInstance(serverName *C.char, configurationJSON *C.char) int {
var dataStore datastore.DataStore var dataStore datastore.DataStore
switch configuration.DataStore { switch configuration.DataStore {
case config.DataStoreBadger: case config.DataStoreBadger:
dataStore = badgerdatastore.NewBadgerDataStore() dataStore = badgerdatastore.NewBadgerDataStore(badgerdatastore.BadgerDataStoreOptions{
PersistDataFilePath: configuration.PersistDataFilePath,
})
default: default:
dataStore = mapdatastore.NewMapDataStore(mapdatastore.MapDataStoreOptions{ dataStore = jsondatastore.NewJsonDataStore(jsondatastore.JsonDataStoreOptions{
InitialDataFilePath: configuration.InitialDataFilePath, InitialDataFilePath: configuration.InitialDataFilePath,
PersistDataFilePath: configuration.PersistDataFilePath, PersistDataFilePath: configuration.PersistDataFilePath,
}) })
@@ -65,6 +67,7 @@ func StopServerInstance(serverName *C.char) int {
if serverInstance, ok := getInstance(serverNameStr); ok { if serverInstance, ok := getInstance(serverNameStr); ok {
serverInstance.server.Stop() serverInstance.server.Stop()
serverInstance.dataStore.Close()
removeInstance(serverNameStr) removeInstance(serverNameStr)
return ResponseSuccess return ResponseSuccess
} }
@@ -93,14 +96,14 @@ func LoadServerInstanceState(serverName *C.char, stateJSON *C.char) int {
stateJSONStr := C.GoString(stateJSON) stateJSONStr := C.GoString(stateJSON)
if serverInstance, ok := getInstance(serverNameStr); ok { if serverInstance, ok := getInstance(serverNameStr); ok {
if mapDS, ok := serverInstance.dataStore.(*mapdatastore.MapDataStore); ok { if jsonDS, ok := serverInstance.dataStore.(*jsondatastore.JsonDataStore); ok {
err := mapDS.LoadStateJSON(stateJSONStr) err := jsonDS.LoadStateJSON(stateJSONStr)
if err != nil { if err != nil {
return ResponseFailedToLoadState return ResponseFailedToLoadState
} }
return ResponseSuccess return ResponseSuccess
} }
return ResponseCurentDataStoreDoesNotSupportStateLoading return ResponseCurrentDataStoreDoesNotSupportStateLoading
} }
return ResponseServerInstanceNotFound return ResponseServerInstanceNotFound