github.com/altipla-consulting/ravendb-go-client@v0.1.3/multi_get_command.go (about) 1 package ravendb 2 3 import ( 4 "encoding/json" 5 "io" 6 "io/ioutil" 7 "net/http" 8 ) 9 10 var _ RavenCommand = &MultiGetCommand{} 11 12 // MultiGetCommand represents multi get command 13 type MultiGetCommand struct { 14 RavenCommandBase 15 16 cache *httpCache 17 commands []*getRequest 18 baseURL string 19 20 Result []*GetResponse // in Java we inherit from List<GetResponse> 21 } 22 23 func newMultiGetCommand(cache *httpCache, commands []*getRequest) *MultiGetCommand { 24 25 cmd := &MultiGetCommand{ 26 RavenCommandBase: NewRavenCommandBase(), 27 28 cache: cache, 29 commands: commands, 30 } 31 cmd.ResponseType = RavenCommandResponseTypeRaw 32 return cmd 33 } 34 35 func (c *MultiGetCommand) createRequest(node *ServerNode) (*http.Request, error) { 36 c.baseURL = node.URL + "/databases/" + node.Database 37 38 m := map[string]interface{}{} 39 var requests []map[string]interface{} 40 41 for _, command := range c.commands { 42 v := map[string]interface{}{} 43 cacheKey, _ := c.getCacheKey(command) 44 { 45 item, cachedChangeVector, _ := c.cache.get(cacheKey) 46 headers := map[string]string{} 47 if cachedChangeVector != nil { 48 headers[headersIfNoneMatch] = "\"" + *cachedChangeVector + "\"" 49 } 50 for k, v := range command.headers { 51 headers[k] = v 52 } 53 v["Url"] = "/databases/" + node.Database + command.url 54 v["Query"] = command.query 55 if command.method == "" { 56 v["Method"] = nil 57 } else { 58 v["Method"] = command.method 59 } 60 v["Headers"] = headers 61 if command.content != nil { 62 v["Content"] = command.content.writeContent() 63 } else { 64 v["Content"] = nil 65 } 66 67 item.close() 68 } 69 requests = append(requests, v) 70 } 71 72 m["Requests"] = requests 73 d, err := jsonMarshal(m) 74 if err != nil { 75 return nil, err 76 } 77 78 uri := c.baseURL + "/multi_get" 79 return newHttpPost(uri, d) 80 } 81 82 func (c *MultiGetCommand) getCacheKey(command *getRequest) (string, string) { 83 uri := c.baseURL + command.getUrlAndQuery() 84 key := command.method + "-" + uri 85 return key, uri 86 } 87 88 type getResponseJSON struct { 89 Result json.RawMessage `json:"Result"` 90 StatusCode int `json:"StatusCode"` 91 Headers map[string]string `json:"Headers"` 92 } 93 94 type resultsJSON struct { 95 Results []*getResponseJSON `json:"Results"` 96 } 97 98 func (c *MultiGetCommand) setResponseRaw(response *http.Response, stream io.Reader) error { 99 var results *resultsJSON 100 d, err := ioutil.ReadAll(stream) 101 if err != nil { 102 return err 103 } 104 err = jsonUnmarshal(d, &results) 105 if err != nil { 106 return err 107 } 108 109 for i, rsp := range results.Results { 110 command := c.commands[i] 111 var getResponse GetResponse 112 113 getResponse.StatusCode = rsp.StatusCode 114 getResponse.Headers = rsp.Headers 115 getResponse.Result = rsp.Result 116 117 c.maybeSetCache(&getResponse, command) 118 c.maybeReadFromCache(&getResponse, command) 119 120 c.Result = append(c.Result, &getResponse) 121 } 122 123 return nil 124 } 125 126 func (c *MultiGetCommand) maybeReadFromCache(getResponse *GetResponse, command *getRequest) { 127 if getResponse.StatusCode != http.StatusNotModified { 128 return 129 } 130 131 cacheKey, _ := c.getCacheKey(command) 132 { 133 cacheItem, _, cachedResponse := c.cache.get(cacheKey) 134 getResponse.Result = cachedResponse 135 cacheItem.close() 136 } 137 } 138 139 func (c *MultiGetCommand) maybeSetCache(getResponse *GetResponse, command *getRequest) { 140 if getResponse.StatusCode == http.StatusNotModified { 141 return 142 } 143 144 cacheKey, _ := c.getCacheKey(command) 145 146 result := getResponse.Result 147 if len(result) == 0 { 148 return 149 } 150 151 changeVector := gttpExtensionsGetEtagHeaderFromMap(getResponse.Headers) 152 if changeVector == nil { 153 return 154 } 155 156 c.cache.set(cacheKey, changeVector, result) 157 }