@@ -6,19 +6,22 @@ import (
66 "errors"
77 "fmt"
88 "net/http"
9+ "os"
910 "strings"
1011 "sync"
1112 "time"
1213
1314 "github.com/buraksezer/olric"
1415 "github.com/buraksezer/olric/config"
1516 "github.com/darkweak/storages/core"
16- lz4 "github.com/pierrec/lz4/v4"
17+ "github.com/google/uuid"
18+ "github.com/pierrec/lz4/v4"
19+ "gopkg.in/yaml.v3"
1720)
1821
1922// Olric provider type.
2023type Olric struct {
21- * olric.ClusterClient
24+ olric.Client
2225 dm * sync.Pool
2326 stale time.Duration
2427 logger core.Logger
@@ -27,15 +30,121 @@ type Olric struct {
2730 configuration config.Client
2831}
2932
33+ func tryToLoadConfiguration (olricInstance * config.Config , olricConfiguration core.CacheProvider , logger core.Logger ) (* config.Config , bool ) {
34+ var err error
35+
36+ isAlreadyLoaded := false
37+
38+ if olricConfiguration .Configuration == nil && olricConfiguration .Path != "" {
39+ if olricInstance , err = config .Load (olricConfiguration .Path ); err == nil {
40+ isAlreadyLoaded = true
41+ }
42+ } else if olricConfiguration .Configuration != nil {
43+ tmpFile := "/tmp/" + uuid .NewString () + ".yml"
44+ yamlConfig , _ := yaml .Marshal (olricConfiguration .Configuration )
45+
46+ defer func () {
47+ if err = os .RemoveAll (tmpFile ); err != nil {
48+ logger .Error ("Impossible to remove the temporary file" )
49+ }
50+ }()
51+
52+ if err = os .WriteFile (
53+ tmpFile ,
54+ yamlConfig ,
55+ 0o600 ,
56+ ); err != nil {
57+ logger .Error ("Impossible to create the embedded Olric config from the given one" )
58+ }
59+
60+ if olricInstance , err = config .Load (tmpFile ); err == nil {
61+ isAlreadyLoaded = true
62+ } else {
63+ logger .Error ("Impossible to create the embedded Olric config from the given one" )
64+ }
65+ }
66+
67+ return olricInstance , isAlreadyLoaded
68+ }
69+
70+ func newEmbeddedOlric (olricConfiguration core.CacheProvider , logger core.Logger ) (* olric.EmbeddedClient , error ) {
71+ var olricInstance * config.Config
72+
73+ var loaded bool
74+
75+ if olricInstance , loaded = tryToLoadConfiguration (olricInstance , olricConfiguration , logger ); ! loaded {
76+ olricInstance = config .New ("local" )
77+ olricInstance .DMaps .MaxInuse = 512 << 20
78+ }
79+
80+ started , cancel := context .WithCancel (context .Background ())
81+ olricInstance .Started = func () {
82+ logger .Error ("Embedded Olric is ready" )
83+
84+ defer cancel ()
85+ }
86+
87+ olricDB , err := olric .New (olricInstance )
88+ if err != nil {
89+ return nil , err
90+ }
91+
92+ errCh := make (chan error , 1 )
93+ defer func () {
94+ close (errCh )
95+ }()
96+
97+ go func (cdb * olric.Olric ) {
98+ if err = cdb .Start (); err != nil {
99+ errCh <- err
100+ }
101+ }(olricDB )
102+
103+ select {
104+ case err = <- errCh :
105+ case <- started .Done ():
106+ }
107+
108+ dbClient := olricDB .NewEmbeddedClient ()
109+
110+ logger .Info ("Embedded Olric is ready for this node." )
111+
112+ return dbClient , nil
113+ }
114+
30115// Factory function create new Olric instance.
31116func Factory (olricConfiguration core.CacheProvider , logger core.Logger , stale time.Duration ) (core.Storer , error ) {
117+ if olricConfiguration .URL == "" && olricConfiguration .Configuration != nil {
118+ if olricCfg , ok := olricConfiguration .Configuration .(map [string ]interface {}); ok {
119+ if mode , found := olricCfg ["mode" ]; found && mode .(string ) == "local" {
120+ logger .Debug ("Olric configuration URL is empty, trying to load olric in embedded mode" )
121+
122+ client , err := newEmbeddedOlric (olricConfiguration , logger )
123+ if err != nil {
124+ logger .Error ("Impossible to setup Embedded Olric instance" )
125+
126+ return nil , err
127+ }
128+
129+ return & Olric {
130+ Client : client ,
131+ dm : nil ,
132+ stale : stale ,
133+ logger : logger ,
134+ configuration : config.Client {},
135+ addresses : strings .Split (olricConfiguration .URL , "," ),
136+ }, nil
137+ }
138+ }
139+ }
140+
32141 client , err := olric .NewClusterClient (strings .Split (olricConfiguration .URL , "," ))
33142 if err != nil {
34143 logger .Errorf ("Impossible to connect to Olric, %v" , err )
35144 }
36145
37146 return & Olric {
38- ClusterClient : client ,
147+ Client : client ,
39148 dm : nil ,
40149 stale : stale ,
41150 logger : logger ,
@@ -290,31 +399,27 @@ func (provider *Olric) DeleteMany(key string) {
290399
291400// Init method will initialize Olric provider if needed.
292401func (provider * Olric ) Init () error {
293- dmap := sync.Pool {
402+ provider . dm = & sync.Pool {
294403 New : func () interface {} {
295- dmap , _ := provider .ClusterClient .NewDMap ("souin-map" )
404+ dmap , _ := provider .Client .NewDMap ("souin-map" )
296405
297406 return dmap
298407 },
299408 }
300409
301- provider .dm = & dmap
302-
303410 return nil
304411}
305412
306413// Reset method will reset or close provider.
307414func (provider * Olric ) Reset () error {
308- provider .ClusterClient .Close (context .Background ())
309-
310- return nil
415+ return provider .Client .Close (context .Background ())
311416}
312417
313418func (provider * Olric ) Reconnect () {
314419 provider .reconnecting = true
315420
316421 if c , err := olric .NewClusterClient (provider .addresses , olric .WithConfig (& provider .configuration )); err == nil && c != nil {
317- provider .ClusterClient = c
422+ provider .Client = c
318423 provider .reconnecting = false
319424 } else {
320425 time .Sleep (10 * time .Second )
0 commit comments