github.com/abolfazlbeh/zhycan@v0.0.0-20230819144214-24cf38237387/internal/watcher/manager.go (about) 1 package watcher 2 3 import ( 4 "fmt" 5 "github.com/abolfazlbeh/zhycan/internal/config" 6 "github.com/radovskyb/watcher" 7 "log" 8 "regexp" 9 "sync" 10 "time" 11 ) 12 13 // Mark: manager 14 15 // Manager object 16 type manager struct { 17 name string 18 watcher *watcher.Watcher 19 lock sync.Mutex 20 isInitialized bool 21 printWatchedFiles bool 22 watchInterval int 23 } 24 25 type watchDirStruct struct { 26 Path string 27 Recursive bool 28 } 29 30 // MARK: Module variables 31 var managerInstance *manager = nil 32 var once sync.Once 33 34 // MARK: Module Initializer 35 func init() { 36 log.Println("Initializing Watcher Manager ...") 37 } 38 39 // MARK: Private Methods 40 41 // init - Constructor -> It initializes the config configuration params 42 func (m *manager) init() { 43 log.Println("Constructing Watcher Manager ...") 44 45 m.name = "watcher" 46 m.isInitialized = false 47 m.printWatchedFiles = false 48 m.watchInterval = 100 49 50 m.lock.Lock() 51 defer m.lock.Unlock() 52 53 // read filter options 54 filterOptions, err := config.GetManager().Get(m.name, "filter_operations") 55 if err != nil { 56 return 57 } 58 59 var filterOptionsArray []string 60 for _, v := range filterOptions.([]interface{}) { 61 filterOptionsArray = append(filterOptionsArray, v.(string)) 62 } 63 64 filterHooks, err := config.GetManager().Get(m.name, "filter_hooks") 65 if err != nil { 66 return 67 } 68 69 var filterHooksArray []string 70 for _, v := range filterHooks.([]interface{}) { 71 filterHooksArray = append(filterHooksArray, v.(string)) 72 } 73 74 maxEvent, err := config.GetManager().Get(m.name, "max_event") 75 if err != nil { 76 return 77 } 78 79 printWatchedFiles, err := config.GetManager().Get(m.name, "print_watched_files") 80 if err != nil { 81 return 82 } 83 m.printWatchedFiles = printWatchedFiles.(bool) 84 85 watchInterval, err := config.GetManager().Get(m.name, "watch_interval") 86 if err != nil { 87 return 88 } 89 m.watchInterval = watchInterval.(int) 90 91 var watchDirs []watchDirStruct 92 watchDirsObj, err := config.GetManager().Get(m.name, "watch_dirs") 93 if err != nil { 94 return 95 } 96 97 for _, v := range watchDirsObj.([]interface{}) { 98 item := v.(map[string]interface{}) 99 watchDirs = append(watchDirs, watchDirStruct{ 100 Path: item["path"].(string), 101 Recursive: item["recursive"].(bool), 102 }) 103 } 104 105 // Let's config a watcher 106 m.watcher = watcher.New() 107 108 var filterOps []watcher.Op 109 for _, item := range filterOptionsArray { 110 switch item { 111 case "create": 112 filterOps = append(filterOps, watcher.Create) 113 break 114 case "move": 115 filterOps = append(filterOps, watcher.Move) 116 break 117 case "rename": 118 filterOps = append(filterOps, watcher.Rename) 119 break 120 case "remove": 121 filterOps = append(filterOps, watcher.Remove) 122 break 123 case "write": 124 filterOps = append(filterOps, watcher.Write) 125 break 126 } 127 } 128 129 m.watcher.FilterOps(filterOps...) 130 131 for _, item := range filterHooksArray { 132 m.watcher.AddFilterHook(watcher.RegexFilterHook( 133 regexp.MustCompile(item), false)) 134 } 135 136 m.watcher.SetMaxEvents(maxEvent.(int)) 137 138 for _, item := range watchDirs { 139 if item.Recursive { 140 if err := m.watcher.AddRecursive(item.Path); err != nil { 141 continue 142 } 143 } else { 144 if err := m.watcher.Add(item.Path); err != nil { 145 continue 146 } 147 } 148 } 149 150 m.isInitialized = true 151 } 152 153 // restartOnChangeConfig - subscribe a function for when the config is changed 154 func (m *manager) restartOnChangeConfig() { 155 m.lock.Lock() 156 defer m.lock.Unlock() 157 158 // Config config server to reload 159 wrapper, err := config.GetManager().GetConfigWrapper(m.name) 160 if err == nil { 161 wrapper.RegisterChangeCallback(func() interface{} { 162 m.Stop() 163 m.init() 164 m.Start() 165 return nil 166 }) 167 } else { 168 // TODO: make some logs 169 } 170 } 171 172 // MARK: Public Functions 173 174 // GetManager - This function returns singleton instance of Logger Manager 175 func GetManager() *manager { 176 // once used for prevent race condition and manage critical section. 177 once.Do(func() { 178 managerInstance = &manager{} 179 managerInstance.init() 180 managerInstance.restartOnChangeConfig() 181 }) 182 return managerInstance 183 } 184 185 // Start - start the watcher and listen for changes 186 func (m *manager) Start() (bool, error) { 187 m.lock.Lock() 188 defer m.lock.Unlock() 189 190 if m.printWatchedFiles { 191 for path, f := range m.watcher.WatchedFiles() { 192 fmt.Printf("%s: %s\n", path, f.Name()) 193 } 194 } 195 196 if err := m.watcher.Start(time.Millisecond * time.Duration(m.watchInterval)); err != nil { 197 return false, NewStartWatcherErr(err) 198 } 199 200 return true, nil 201 } 202 203 // Stop - stop the watcher and listen for changes 204 func (m *manager) Stop() { 205 m.lock.Lock() 206 defer m.lock.Unlock() 207 208 m.watcher.Close() 209 <-m.watcher.Closed 210 }