6 st "github.com/iotbzh/xds-agent/lib/syncthing"
7 "github.com/iotbzh/xds-agent/lib/xaapiv1"
8 "github.com/iotbzh/xds-server/lib/xsapiv1"
11 // IPROJECT interface implementation for syncthing projects
14 type STProject struct {
17 folder *xsapiv1.FolderConfig
21 // NewProjectST Create a new instance of STProject
22 func NewProjectST(ctx *Context, svr *XdsServer) *STProject {
26 folder: &xsapiv1.FolderConfig{},
32 func (p *STProject) Add(cfg xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
35 // Add project/folder into XDS Server
36 err = p.server.FolderAdd(p.server.ProjectToFolder(cfg), p.folder)
40 svrPrj := p.GetProject()
42 // Declare project into local Syncthing
43 id, err := p.SThg.FolderChange(st.FolderChangeArg{
46 RelativePath: cfg.ClientPath,
47 SyncThingID: p.server.ServerConfig.Builder.SyncThingID,
53 locPrj, err := p.SThg.FolderConfigGet(id)
55 svrPrj.Status = xaapiv1.StatusErrorConfig
58 if svrPrj.ID != locPrj.ID {
59 p.Log.Errorf("Project ID in XDSServer and local ST differ: %s != %s", svrPrj.ID, locPrj.ID)
62 // Use Setup function to setup remains fields
63 return p.Setup(*svrPrj)
67 func (p *STProject) Delete() error {
68 errSvr := p.server.FolderDelete(p.folder.ID)
69 errLoc := p.SThg.FolderDelete(p.folder.ID)
76 // GetProject Get public part of project config
77 func (p *STProject) GetProject() *xaapiv1.ProjectConfig {
78 prj := p.server.FolderToProject(*p.folder)
79 prj.ServerID = p.server.ID
83 // Setup Setup local project config
84 func (p *STProject) Setup(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
86 p.folder = p.server.ProjectToFolder(prj)
87 svrPrj := p.GetProject()
89 // Register events to update folder status
90 // Register to XDS Server events
91 p.server.EventOn("event:folder-state-change", "", p._cbServerFolderChanged)
92 if err := p.server.EventRegister("folder-state-change", svrPrj.ID); err != nil {
93 p.Log.Warningf("XDS Server EventRegister failed: %v", err)
97 // Register to Local Syncthing events
98 for _, evName := range []string{st.EventStateChanged, st.EventFolderPaused} {
99 evID, err := p.SThg.Events.Register(evName, p._cbLocalSTEvents, svrPrj.ID, nil)
103 p.eventIDs = append(p.eventIDs, evID)
109 // Update Update some field of a project
110 func (p *STProject) Update(prj xaapiv1.ProjectConfig) (*xaapiv1.ProjectConfig, error) {
112 if p.folder.ID != prj.ID {
113 return nil, fmt.Errorf("Invalid id")
116 err := p.server.FolderUpdate(p.server.ProjectToFolder(prj), p.folder)
121 return p.GetProject(), nil
124 // GetServer Get the XdsServer that holds this project
125 func (p *STProject) GetServer() *XdsServer {
129 // Sync Force project files synchronization
130 func (p *STProject) Sync() error {
131 if err := p.server.FolderSync(p.folder.ID); err != nil {
134 return p.SThg.FolderScan(p.folder.ID, "")
137 // IsInSync Check if project files are in-sync
138 func (p *STProject) IsInSync() (bool, error) {
139 // Should be up-to-date by callbacks (see below)
140 return p.folder.IsInSync, nil
147 // callback use to update (XDS Server) folder IsInSync status
149 func (p *STProject) _cbServerFolderChanged(pData interface{}, data interface{}) error {
150 evt := data.(xsapiv1.EventMsg)
152 // Only process event that concerns this project/folder ID
153 if p.folder.ID != evt.Folder.ID {
157 if evt.Folder.IsInSync != p.folder.DataCloudSync.STSvrIsInSync ||
158 evt.Folder.Status != p.folder.DataCloudSync.STSvrStatus {
160 p.folder.DataCloudSync.STSvrIsInSync = evt.Folder.IsInSync
161 p.folder.DataCloudSync.STSvrStatus = evt.Folder.Status
163 if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
164 p.Log.Warningf("Cannot notify project change (from server): %v", err)
170 // callback use to update IsInSync status
171 func (p *STProject) _cbLocalSTEvents(ev st.Event, data *st.EventsCBData) {
173 inSync := p.folder.DataCloudSync.STLocIsInSync
174 sts := p.folder.DataCloudSync.STLocStatus
180 case st.EventStateChanged:
183 case "scanning", "syncing":
184 sts = xaapiv1.StatusSyncing
186 sts = xaapiv1.StatusEnable
188 inSync = (to == "idle")
190 case st.EventFolderPaused:
191 if sts == xaapiv1.StatusEnable {
192 sts = xaapiv1.StatusPause
197 if prevSync != inSync || prevStatus != sts {
199 p.folder.DataCloudSync.STLocIsInSync = inSync
200 p.folder.DataCloudSync.STLocStatus = sts
202 if err := p.events.Emit(xaapiv1.EVTProjectChange, p.server.FolderToProject(*p.folder), ""); err != nil {
203 p.Log.Warningf("Cannot notify project change (local): %v", err)