watcher.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package plugin_manager
  2. import (
  3. "os"
  4. "path"
  5. "github.com/langgenius/dify-plugin-daemon/internal/types/entities"
  6. "github.com/langgenius/dify-plugin-daemon/internal/utils/log"
  7. "github.com/langgenius/dify-plugin-daemon/internal/utils/parser"
  8. )
  9. func startWatcher(path string) {
  10. // load local plugins firstly
  11. for plugin := range loadNewPlugins(path) {
  12. log.Info("loaded plugin: %s:%s", plugin.Config.Name, plugin.Config.Version)
  13. m.Store(plugin.Info.ID, &plugin)
  14. lifetime(&plugin)
  15. }
  16. }
  17. // chan should be closed after using that
  18. func loadNewPlugins(root_path string) <-chan entities.PluginRuntime {
  19. ch := make(chan entities.PluginRuntime)
  20. plugins, err := os.ReadDir(root_path)
  21. if err != nil {
  22. log.Error("no plugin found in path: %s", root_path)
  23. close(ch)
  24. return ch
  25. }
  26. go func() {
  27. for _, plugin := range plugins {
  28. if plugin.IsDir() {
  29. log.Info("found new plugin path: %s", plugin.Name())
  30. configuration_path := path.Join(root_path, plugin.Name(), "manifest.json")
  31. configuration, err := parsePluginConfig(configuration_path)
  32. if err != nil {
  33. log.Error("parse plugin config error: %v", err)
  34. continue
  35. }
  36. status := verifyPluginStatus(configuration)
  37. if status.exist && status.alive {
  38. continue
  39. } else if status.exist && !status.alive {
  40. log.Warn("plugin %s is not alive")
  41. continue
  42. }
  43. ch <- entities.PluginRuntime{
  44. Config: *configuration,
  45. State: entities.PluginRuntimeState{
  46. Restarts: 0,
  47. Active: false,
  48. RelativePath: path.Join(root_path, plugin.Name()),
  49. ActiveAt: nil,
  50. DeadAt: nil,
  51. Verified: false,
  52. },
  53. }
  54. }
  55. }
  56. close(ch)
  57. }()
  58. return ch
  59. }
  60. func parsePluginConfig(configuration_path string) (*entities.PluginConfiguration, error) {
  61. text, err := os.ReadFile(configuration_path)
  62. if err != nil {
  63. return nil, err
  64. }
  65. result, err := parser.UnmarshalJson[entities.PluginConfiguration](string(text))
  66. if err != nil {
  67. return nil, err
  68. }
  69. return &result, nil
  70. }
  71. type pluginStatusResult struct {
  72. exist bool
  73. alive bool
  74. }
  75. func verifyPluginStatus(config *entities.PluginConfiguration) pluginStatusResult {
  76. r, exist := checkPluginExist(config.Name)
  77. if exist {
  78. return pluginStatusResult{
  79. exist: true,
  80. alive: r.State.Active,
  81. }
  82. }
  83. return pluginStatusResult{
  84. exist: false,
  85. alive: false,
  86. }
  87. }