Source file src/cmd/go/internal/cacheprog/cacheprog.go
1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package cacheprog defines the protocol for a GOCACHEPROG program. 6 // 7 // By default, the go command manages a build cache stored in the file system 8 // itself. GOCACHEPROG can be set to the name of a command (with optional 9 // space-separated flags) that implements the go command build cache externally. 10 // This permits defining a different cache policy. 11 // 12 // The go command will start the GOCACHEPROG as a subprocess and communicate 13 // with it via JSON messages over stdin/stdout. The subprocess's stderr will be 14 // connected to the go command's stderr. 15 // 16 // The subprocess should immediately send a [Response] with its capabilities. 17 // After that, the go command will send a stream of [Request] messages and the 18 // subprocess should reply to each [Request] with a [Response] message. 19 package cacheprog 20 21 import ( 22 "io" 23 "time" 24 ) 25 26 // Cmd is a command that can be issued to a child process. 27 // 28 // If the interface needs to grow, the go command can add new commands or new 29 // versioned commands like "get2" in the future. The initial [Response] from 30 // the child process indicates which commands it supports. 31 type Cmd string 32 33 const ( 34 // CmdPut tells the cache program to store an object in the cache. 35 // 36 // [Request.ActionID] is the cache key of this object. The cache should 37 // store [Request.OutputID] and [Request.Body] under this key for a 38 // later "get" request. It must also store the Body in a file in the local 39 // file system and return the path to that file in [Response.DiskPath], 40 // which must exist at least until a "close" request. 41 CmdPut = Cmd("put") 42 43 // CmdGet tells the cache program to retrieve an object from the cache. 44 // 45 // [Request.ActionID] specifies the key of the object to get. If the 46 // cache does not contain this object, it should set [Response.Miss] to 47 // true. Otherwise, it should populate the fields of [Response], 48 // including setting [Response.OutputID] to the OutputID of the original 49 // "put" request and [Response.DiskPath] to the path of a local file 50 // containing the Body of the original "put" request. That file must 51 // continue to exist at least until a "close" request. 52 CmdGet = Cmd("get") 53 54 // CmdClose requests that the cache program exit gracefully. 55 // 56 // The cache program should reply to this request and then exit 57 // (thus closing its stdout). 58 CmdClose = Cmd("close") 59 ) 60 61 // Request is the JSON-encoded message that's sent from the go command to 62 // the GOCACHEPROG child process over stdin. Each JSON object is on its own 63 // line. A ProgRequest of Type "put" with BodySize > 0 will be followed by a 64 // line containing a base64-encoded JSON string literal of the body. 65 type Request struct { 66 // ID is a unique number per process across all requests. 67 // It must be echoed in the Response from the child. 68 ID int64 69 70 // Command is the type of request. 71 // The go command will only send commands that were declared 72 // as supported by the child. 73 Command Cmd 74 75 // ActionID is the cache key for "put" and "get" requests. 76 ActionID []byte `json:",omitempty"` // or nil if not used 77 78 // OutputID is stored with the body for "put" requests. 79 // 80 // Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was 81 // accidentally named ObjectID. It was renamed to OutputID in Go 1.24. 82 OutputID []byte `json:",omitempty"` // or nil if not used 83 84 // Body is the body for "put" requests. It's sent after the JSON object 85 // as a base64-encoded JSON string when BodySize is non-zero. 86 // It's sent as a separate JSON value instead of being a struct field 87 // send in this JSON object so large values can be streamed in both directions. 88 // The base64 string body of a Request will always be written 89 // immediately after the JSON object and a newline. 90 Body io.Reader `json:"-"` 91 92 // BodySize is the number of bytes of Body. If zero, the body isn't written. 93 BodySize int64 `json:",omitempty"` 94 95 // ObjectID is the accidental spelling of OutputID that was used prior to Go 96 // 1.24. 97 // 98 // Deprecated: use OutputID. This field is only populated temporarily for 99 // backwards compatibility with Go 1.23 and earlier when 100 // GOEXPERIMENT=gocacheprog is set. It will be removed in Go 1.25. 101 ObjectID []byte `json:",omitempty"` 102 } 103 104 // Response is the JSON response from the child process to the go command. 105 // 106 // With the exception of the first protocol message that the child writes to its 107 // stdout with ID==0 and KnownCommands populated, these are only sent in 108 // response to a Request from the go command. 109 // 110 // Responses can be sent in any order. The ID must match the request they're 111 // replying to. 112 type Response struct { 113 ID int64 // that corresponds to Request; they can be answered out of order 114 Err string `json:",omitempty"` // if non-empty, the error 115 116 // KnownCommands is included in the first message that cache helper program 117 // writes to stdout on startup (with ID==0). It includes the 118 // Request.Command types that are supported by the program. 119 // 120 // This lets the go command extend the protocol gracefully over time (adding 121 // "get2", etc), or fail gracefully when needed. It also lets the go command 122 // verify the program wants to be a cache helper. 123 KnownCommands []Cmd `json:",omitempty"` 124 125 // For "get" requests. 126 127 Miss bool `json:",omitempty"` // cache miss 128 OutputID []byte `json:",omitempty"` // the ObjectID stored with the body 129 Size int64 `json:",omitempty"` // body size in bytes 130 Time *time.Time `json:",omitempty"` // when the object was put in the cache (optional; used for cache expiration) 131 132 // For "get" and "put" requests. 133 134 // DiskPath is the absolute path on disk of the body corresponding to a 135 // "get" (on cache hit) or "put" request's ActionID. 136 DiskPath string `json:",omitempty"` 137 } 138