github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/cmd/elasticsearch/setup.go (about) 1 // Work in progress 2 package main 3 4 import ( 5 "context" 6 "database/sql" 7 "encoding/json" 8 "errors" 9 "log" 10 "os" 11 "strconv" 12 13 c "github.com/Azareal/Gosora/common" 14 "github.com/Azareal/Gosora/query_gen" 15 "gopkg.in/olivere/elastic.v6" 16 ) 17 18 func main() { 19 log.Print("Loading the configuration data") 20 err := c.LoadConfig() 21 if err != nil { 22 log.Fatal(err) 23 } 24 25 log.Print("Processing configuration data") 26 err = c.ProcessConfig() 27 if err != nil { 28 log.Fatal(err) 29 } 30 31 if c.DbConfig.Adapter != "mysql" && c.DbConfig.Adapter != "" { 32 log.Fatal("Only MySQL is supported for upgrades right now, please wait for a newer build of the patcher") 33 } 34 35 err = prepMySQL() 36 if err != nil { 37 log.Fatal(err) 38 } 39 40 client, err := elastic.NewClient(elastic.SetErrorLog(log.New(os.Stdout, "ES ", log.LstdFlags))) 41 if err != nil { 42 log.Fatal(err) 43 } 44 _, _, err = client.Ping("http://127.0.0.1:9200").Do(context.Background()) 45 if err != nil { 46 log.Fatal(err) 47 } 48 49 err = setupIndices(client) 50 if err != nil { 51 log.Fatal(err) 52 } 53 54 err = setupData(client) 55 if err != nil { 56 log.Fatal(err) 57 } 58 } 59 60 func prepMySQL() error { 61 return qgen.Builder.Init("mysql", map[string]string{ 62 "host": c.DbConfig.Host, 63 "port": c.DbConfig.Port, 64 "name": c.DbConfig.Dbname, 65 "username": c.DbConfig.Username, 66 "password": c.DbConfig.Password, 67 "collation": "utf8mb4_general_ci", 68 }) 69 } 70 71 type ESIndexBase struct { 72 Mappings ESIndexMappings `json:"mappings"` 73 } 74 75 type ESIndexMappings struct { 76 Doc ESIndexDoc `json:"_doc"` 77 } 78 79 type ESIndexDoc struct { 80 Properties map[string]map[string]string `json:"properties"` 81 } 82 83 type ESDocMap map[string]map[string]string 84 85 func (d ESDocMap) Add(column string, cType string) { 86 d["column"] = map[string]string{"type": cType} 87 } 88 89 func setupIndices(client *elastic.Client) error { 90 exists, err := client.IndexExists("topics").Do(context.Background()) 91 if err != nil { 92 return err 93 } 94 if exists { 95 deleteIndex, err := client.DeleteIndex("topics").Do(context.Background()) 96 if err != nil { 97 return err 98 } 99 if !deleteIndex.Acknowledged { 100 return errors.New("delete not acknowledged") 101 } 102 } 103 104 docMap := make(ESDocMap) 105 docMap.Add("tid", "integer") 106 docMap.Add("title", "text") 107 docMap.Add("content", "text") 108 docMap.Add("createdBy", "integer") 109 docMap.Add("ip", "ip") 110 docMap.Add("suggest", "completion") 111 indexBase := ESIndexBase{ESIndexMappings{ESIndexDoc{docMap}}} 112 oBytes, err := json.Marshal(indexBase) 113 if err != nil { 114 return err 115 } 116 createIndex, err := client.CreateIndex("topics").Body(string(oBytes)).Do(context.Background()) 117 if err != nil { 118 return err 119 } 120 if !createIndex.Acknowledged { 121 return errors.New("not acknowledged") 122 } 123 124 exists, err = client.IndexExists("replies").Do(context.Background()) 125 if err != nil { 126 return err 127 } 128 if exists { 129 deleteIndex, err := client.DeleteIndex("replies").Do(context.Background()) 130 if err != nil { 131 return err 132 } 133 if !deleteIndex.Acknowledged { 134 return errors.New("delete not acknowledged") 135 } 136 } 137 138 docMap = make(ESDocMap) 139 docMap.Add("rid", "integer") 140 docMap.Add("tid", "integer") 141 docMap.Add("content", "text") 142 docMap.Add("createdBy", "integer") 143 docMap.Add("ip", "ip") 144 docMap.Add("suggest", "completion") 145 indexBase = ESIndexBase{ESIndexMappings{ESIndexDoc{docMap}}} 146 oBytes, err = json.Marshal(indexBase) 147 if err != nil { 148 return err 149 } 150 createIndex, err = client.CreateIndex("replies").Body(string(oBytes)).Do(context.Background()) 151 if err != nil { 152 return err 153 } 154 if !createIndex.Acknowledged { 155 return errors.New("not acknowledged") 156 } 157 158 return nil 159 } 160 161 type ESTopic struct { 162 ID int `json:"tid"` 163 Title string `json:"title"` 164 Content string `json:"content"` 165 CreatedBy int `json:"createdBy"` 166 IP string `json:"ip"` 167 } 168 169 type ESReply struct { 170 ID int `json:"rid"` 171 TID int `json:"tid"` 172 Content string `json:"content"` 173 CreatedBy int `json:"createdBy"` 174 IP string `json:"ip"` 175 } 176 177 func setupData(client *elastic.Client) error { 178 tcount := 4 179 errs := make(chan error) 180 181 go func() { 182 tin := make([]chan ESTopic, tcount) 183 tf := func(tin chan ESTopic) { 184 for { 185 topic, more := <-tin 186 if !more { 187 break 188 } 189 _, err := client.Index().Index("topics").Type("_doc").Id(strconv.Itoa(topic.ID)).BodyJson(topic).Do(context.Background()) 190 if err != nil { 191 errs <- err 192 } 193 } 194 } 195 for i := 0; i < 4; i++ { 196 go tf(tin[i]) 197 } 198 199 oi := 0 200 err := qgen.NewAcc().Select("topics").Cols("tid,title,content,createdBy,ip").Each(func(rows *sql.Rows) error { 201 t := ESTopic{} 202 err := rows.Scan(&t.ID, &t.Title, &t.Content, &t.CreatedBy, &t.IP) 203 if err != nil { 204 return err 205 } 206 tin[oi] <- t 207 if oi < 3 { 208 oi++ 209 } 210 return nil 211 }) 212 for i := 0; i < 4; i++ { 213 close(tin[i]) 214 } 215 errs <- err 216 }() 217 218 go func() { 219 rin := make([]chan ESReply, tcount) 220 rf := func(rin chan ESReply) { 221 for { 222 reply, more := <-rin 223 if !more { 224 break 225 } 226 _, err := client.Index().Index("replies").Type("_doc").Id(strconv.Itoa(reply.ID)).BodyJson(reply).Do(context.Background()) 227 if err != nil { 228 errs <- err 229 } 230 } 231 } 232 for i := 0; i < 4; i++ { 233 rf(rin[i]) 234 } 235 oi := 0 236 err := qgen.NewAcc().Select("replies").Cols("rid,tid,content,createdBy,ip").Each(func(rows *sql.Rows) error { 237 r := ESReply{} 238 err := rows.Scan(&r.ID, &r.TID, &r.Content, &r.CreatedBy, &r.IP) 239 if err != nil { 240 return err 241 } 242 rin[oi] <- r 243 if oi < 3 { 244 oi++ 245 } 246 return nil 247 }) 248 for i := 0; i < 4; i++ { 249 close(rin[i]) 250 } 251 errs <- err 252 }() 253 254 fin := 0 255 for { 256 err := <-errs 257 if err == nil { 258 fin++ 259 if fin == 2 { 260 return nil 261 } 262 } else { 263 return err 264 } 265 } 266 }