4 "github.com/iotbzh/xds-agent/lib/apiv1"
5 st "github.com/iotbzh/xds-agent/lib/syncthing"
8 // IPROJECT interface implementation for syncthing projects
11 type STProject struct {
14 folder *XdsFolderConfig
18 // NewProjectST Create a new instance of STProject
19 func NewProjectST(ctx *Context, svr *XdsServer) *STProject {
23 folder: &XdsFolderConfig{},
29 func (p *STProject) Add(cfg apiv1.ProjectConfig) (*apiv1.ProjectConfig, error) {
32 // Add project/folder into XDS Server
33 err = p.server.FolderAdd(p.server.ProjectToFolder(cfg), p.folder)
37 svrPrj := p.GetProject()
39 // Declare project into local Syncthing
40 id, err := p.SThg.FolderChange(st.FolderChangeArg{
43 RelativePath: cfg.ClientPath,
44 SyncThingID: p.server.ServerConfig.Builder.SyncThingID,
50 locPrj, err := p.SThg.FolderConfigGet(id)
52 svrPrj.Status = apiv1.StatusErrorConfig
55 if svrPrj.ID != locPrj.ID {
56 p.Log.Errorf("Project ID in XDSServer and local ST differ: %s != %s", svrPrj.ID, locPrj.ID)
59 // Use Update function to setup remains fields
60 return p.UpdateProject(*svrPrj)
64 func (p *STProject) Delete() error {
65 errSvr := p.server.FolderDelete(p.folder.ID)
66 errLoc := p.SThg.FolderDelete(p.folder.ID)
73 // GetProject Get public part of project config
74 func (p *STProject) GetProject() *apiv1.ProjectConfig {
75 prj := p.server.FolderToProject(*p.folder)
76 prj.ServerID = p.server.ID
80 // UpdateProject Update project config
81 func (p *STProject) UpdateProject(prj apiv1.ProjectConfig) (*apiv1.ProjectConfig, error) {
83 p.folder = p.server.ProjectToFolder(prj)
84 svrPrj := p.GetProject()
86 // Register events to update folder status
87 // Register to XDS Server events
88 p.server.EventOn("event:FolderStateChanged", p._cbServerFolderChanged)
89 if err := p.server.EventRegister("FolderStateChanged", svrPrj.ID); err != nil {
90 p.Log.Warningf("XDS Server EventRegister failed: %v", err)
94 // Register to Local Syncthing events
95 for _, evName := range []string{st.EventStateChanged, st.EventFolderPaused} {
96 evID, err := p.SThg.Events.Register(evName, p._cbLocalSTEvents, svrPrj.ID, nil)
100 p.eventIDs = append(p.eventIDs, evID)
106 // GetServer Get the XdsServer that holds this project
107 func (p *STProject) GetServer() *XdsServer {
111 // Sync Force project files synchronization
112 func (p *STProject) Sync() error {
113 if err := p.server.FolderSync(p.folder.ID); err != nil {
116 return p.SThg.FolderScan(p.folder.ID, "")
119 // IsInSync Check if project files are in-sync
120 func (p *STProject) IsInSync() (bool, error) {
121 // Should be up-to-date by callbacks (see below)
122 return p.folder.IsInSync, nil
129 // callback use to update (XDS Server) folder IsInSync status
131 func (p *STProject) _cbServerFolderChanged(data interface{}) {
132 evt := data.(XdsEventFolderChange)
134 // Only process event that concerns this project/folder ID
135 if p.folder.ID != evt.Folder.ID {
139 if evt.Folder.IsInSync != p.folder.DataCloudSync.STSvrIsInSync ||
140 evt.Folder.Status != p.folder.DataCloudSync.STSvrStatus {
142 p.folder.DataCloudSync.STSvrIsInSync = evt.Folder.IsInSync
143 p.folder.DataCloudSync.STSvrStatus = evt.Folder.Status
145 if err := p.events.Emit(apiv1.EVTProjectChange, p.server.FolderToProject(*p.folder)); err != nil {
146 p.Log.Warningf("Cannot notify project change: %v", err)
151 // callback use to update IsInSync status
152 func (p *STProject) _cbLocalSTEvents(ev st.Event, data *st.EventsCBData) {
154 inSync := p.folder.DataCloudSync.STLocIsInSync
155 sts := p.folder.DataCloudSync.STLocStatus
161 case st.EventStateChanged:
164 case "scanning", "syncing":
165 sts = apiv1.StatusSyncing
167 sts = apiv1.StatusEnable
169 inSync = (to == "idle")
171 case st.EventFolderPaused:
172 if sts == apiv1.StatusEnable {
173 sts = apiv1.StatusPause
178 if prevSync != inSync || prevStatus != sts {
180 p.folder.DataCloudSync.STLocIsInSync = inSync
181 p.folder.DataCloudSync.STLocStatus = sts
183 if err := p.events.Emit(apiv1.EVTProjectChange, p.server.FolderToProject(*p.folder)); err != nil {
184 p.Log.Warningf("Cannot notify project change: %v", err)