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  }