persistent_store.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package surge
  2. import (
  3. "github.com/sagernet/sing-box/adapter"
  4. "github.com/sagernet/sing-box/script/jsc"
  5. "github.com/sagernet/sing-box/script/modules/boxctx"
  6. "github.com/sagernet/sing/service"
  7. "github.com/dop251/goja"
  8. )
  9. type PersistentStore struct {
  10. class jsc.Class[*Module, *PersistentStore]
  11. cacheFile adapter.CacheFile
  12. inMemoryCache *adapter.SurgeInMemoryCache
  13. tag string
  14. }
  15. func createPersistentStore(module *Module) jsc.Class[*Module, *PersistentStore] {
  16. class := jsc.NewClass[*Module, *PersistentStore](module)
  17. class.DefineMethod("get", (*PersistentStore).get)
  18. class.DefineMethod("set", (*PersistentStore).set)
  19. class.DefineMethod("toString", (*PersistentStore).toString)
  20. return class
  21. }
  22. func newPersistentStore(class jsc.Class[*Module, *PersistentStore]) goja.Value {
  23. boxCtx := boxctx.MustFromRuntime(class.Runtime())
  24. return class.New(&PersistentStore{
  25. class: class,
  26. cacheFile: service.FromContext[adapter.CacheFile](boxCtx.Context),
  27. inMemoryCache: service.FromContext[adapter.ScriptManager](boxCtx.Context).SurgeCache(),
  28. tag: boxCtx.Tag,
  29. })
  30. }
  31. func (s *PersistentStore) get(call goja.FunctionCall) any {
  32. key := jsc.AssertString(s.class.Runtime(), call.Argument(0), "key", true)
  33. if key == "" {
  34. key = s.tag
  35. }
  36. var value string
  37. if s.cacheFile != nil {
  38. value = s.cacheFile.SurgePersistentStoreRead(key)
  39. } else {
  40. s.inMemoryCache.RLock()
  41. value = s.inMemoryCache.Data[key]
  42. s.inMemoryCache.RUnlock()
  43. }
  44. if value == "" {
  45. return goja.Null()
  46. } else {
  47. return value
  48. }
  49. }
  50. func (s *PersistentStore) set(call goja.FunctionCall) any {
  51. data := jsc.AssertString(s.class.Runtime(), call.Argument(0), "data", true)
  52. key := jsc.AssertString(s.class.Runtime(), call.Argument(1), "key", true)
  53. if key == "" {
  54. key = s.tag
  55. }
  56. if s.cacheFile != nil {
  57. err := s.cacheFile.SurgePersistentStoreWrite(key, data)
  58. if err != nil {
  59. panic(s.class.Runtime().NewGoError(err))
  60. }
  61. } else {
  62. s.inMemoryCache.Lock()
  63. s.inMemoryCache.Data[key] = data
  64. s.inMemoryCache.Unlock()
  65. }
  66. return goja.Undefined()
  67. }
  68. func (s *PersistentStore) toString(call goja.FunctionCall) any {
  69. return "[sing-box Surge persistentStore]"
  70. }