Skip to content

Commit a63aee4

Browse files
aclementsgopherbot
authored andcommitted
cmd/go: improve GOCACHEPROG types documentation
This is in preparation for adding a "go help" topic for GOCACHEPROG. Updates #71032 Updates #59719 Change-Id: I9dbbe56fa328dffe89207b5b41a0f37afd51e2b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/638566 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Austin Clements <[email protected]> Reviewed-by: Michael Matloob <[email protected]>
1 parent 847c357 commit a63aee4

File tree

2 files changed

+72
-29
lines changed

2 files changed

+72
-29
lines changed

src/cmd/go/internal/cache/cache.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ type Cache interface {
3838
// Get returns the cache entry for the provided ActionID.
3939
// On miss, the error type should be of type *entryNotFoundError.
4040
//
41-
// After a success call to Get, OutputFile(Entry.OutputID) must
42-
// exist on disk for until Close is called (at the end of the process).
41+
// After a successful call to Get, OutputFile(Entry.OutputID) must
42+
// exist on disk until Close is called (at the end of the process).
4343
Get(ActionID) (Entry, error)
4444

4545
// Put adds an item to the cache.
@@ -50,14 +50,14 @@ type Cache interface {
5050
// As a special case, if the ReadSeeker is of type noVerifyReadSeeker,
5151
// the verification from GODEBUG=goverifycache=1 is skipped.
5252
//
53-
// After a success call to Get, OutputFile(Entry.OutputID) must
54-
// exist on disk for until Close is called (at the end of the process).
53+
// After a successful call to Put, OutputFile(OutputID) must
54+
// exist on disk until Close is called (at the end of the process).
5555
Put(ActionID, io.ReadSeeker) (_ OutputID, size int64, _ error)
5656

5757
// Close is called at the end of the go process. Implementations can do
5858
// cache cleanup work at this phase, or wait for and report any errors from
59-
// background cleanup work started earlier. Any cache trimming should in one
60-
// process should not violate cause the invariants of this interface to be
59+
// background cleanup work started earlier. Any cache trimming in one
60+
// process should not cause the invariants of this interface to be
6161
// violated in another process. Namely, a cache trim from one process should
6262
// not delete an ObjectID from disk that was recently Get or Put from
6363
// another process. As a rule of thumb, don't trim things used in the last

src/cmd/go/internal/cache/prog.go

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,36 +63,74 @@ type ProgCache struct {
6363
writeMu sync.Mutex
6464
}
6565

66+
// The following types define the protocol for a GOCACHEPROG program.
67+
//
68+
// By default, the go command manages a build cache stored in the file system
69+
// itself. GOCACHEPROG can be set to the name of a command (with optional
70+
// space-separated flags) that implements the go command build cache externally.
71+
// This permits defining a different cache policy.
72+
//
73+
// The go command will start the GOCACHEPROG as a subprocess and communicate
74+
// with it via JSON messages over stdin/stdout. The subprocess's stderr will be
75+
// connected to the go command's stderr.
76+
//
77+
// The subprocess should immediately send a [ProgResponse] with its capabilities.
78+
// After that, the go command will send a stream of [ProgRequest] messages and the
79+
// subprocess should reply to each [ProgRequest] with a [ProgResponse] message.
80+
6681
// ProgCmd is a command that can be issued to a child process.
6782
//
68-
// If the interface needs to grow, we can add new commands or new versioned
69-
// commands like "get2".
83+
// If the interface needs to grow, the go command can add new commands or new
84+
// versioned commands like "get2" in the future. The initial [ProgResponse] from
85+
// the child process indicates which commands it supports.
7086
type ProgCmd string
7187

7288
const (
73-
cmdGet = ProgCmd("get")
74-
cmdPut = ProgCmd("put")
89+
// cmdPut tells the cache program to store an object in the cache.
90+
//
91+
// [ProgRequest.ActionID] is the cache key of this object. The cache should
92+
// store [ProgRequest.OutputID] and [ProgRequest.Body] under this key for a
93+
// later "get" request. It must also store the Body in a file in the local
94+
// file system and return the path to that file in [ProgResponse.DiskPath],
95+
// which must exist at least until a "close" request.
96+
cmdPut = ProgCmd("put")
97+
98+
// cmdGet tells the cache program to retrieve an object from the cache.
99+
//
100+
// [ProgRequest.ActionID] specifies the key of the object to get. If the
101+
// cache does not contain this object, it should set [ProgResponse.Miss] to
102+
// true. Otherwise, it should populate the fields of [ProgResponse],
103+
// including setting [ProgResponse.OutputID] to the OutputID of the original
104+
// "put" request and [ProgResponse.DiskPath] to the path of a local file
105+
// containing the Body of the original "put" request. That file must
106+
// continue to exist at least until a "close" request.
107+
cmdGet = ProgCmd("get")
108+
109+
// cmdClose requests that the cache program exit gracefully.
110+
//
111+
// The cache program should reply to this request and then exit
112+
// (thus closing its stdout).
75113
cmdClose = ProgCmd("close")
76114
)
77115

78-
// ProgRequest is the JSON-encoded message that's sent from cmd/go to
79-
// the GOCACHEPROG child process over stdin. Each JSON object is on its
80-
// own line. A ProgRequest of Type "put" with BodySize > 0 will be followed
81-
// by a line containing a base64-encoded JSON string literal of the body.
116+
// ProgRequest is the JSON-encoded message that's sent from the go command to
117+
// the GOCACHEPROG child process over stdin. Each JSON object is on its own
118+
// line. A ProgRequest of Type "put" with BodySize > 0 will be followed by a
119+
// line containing a base64-encoded JSON string literal of the body.
82120
type ProgRequest struct {
83121
// ID is a unique number per process across all requests.
84122
// It must be echoed in the ProgResponse from the child.
85123
ID int64
86124

87125
// Command is the type of request.
88-
// The cmd/go tool will only send commands that were declared
126+
// The go command will only send commands that were declared
89127
// as supported by the child.
90128
Command ProgCmd
91129

92-
// ActionID is non-nil for get and puts.
130+
// ActionID is the cache key for "put" and "get" requests.
93131
ActionID []byte `json:",omitempty"` // or nil if not used
94132

95-
// OutputID is set for Type "put".
133+
// OutputID is stored with the body for "put" requests.
96134
//
97135
// Prior to Go 1.24, when GOCACHEPROG was still an experiment, this was
98136
// accidentally named ObjectID. It was renamed to OutputID in Go 1.24.
@@ -118,11 +156,11 @@ type ProgRequest struct {
118156
ObjectID []byte `json:",omitempty"`
119157
}
120158

121-
// ProgResponse is the JSON response from the child process to cmd/go.
159+
// ProgResponse is the JSON response from the child process to the go command.
122160
//
123161
// With the exception of the first protocol message that the child writes to its
124162
// stdout with ID==0 and KnownCommands populated, these are only sent in
125-
// response to a ProgRequest from cmd/go.
163+
// response to a ProgRequest from the go command.
126164
//
127165
// ProgResponses can be sent in any order. The ID must match the request they're
128166
// replying to.
@@ -134,21 +172,22 @@ type ProgResponse struct {
134172
// writes to stdout on startup (with ID==0). It includes the
135173
// ProgRequest.Command types that are supported by the program.
136174
//
137-
// This lets us extend the protocol gracefully over time (adding "get2",
138-
// etc), or fail gracefully when needed. It also lets us verify the program
139-
// wants to be a cache helper.
175+
// This lets the go command extend the protocol gracefully over time (adding
176+
// "get2", etc), or fail gracefully when needed. It also lets the go command
177+
// verify the program wants to be a cache helper.
140178
KnownCommands []ProgCmd `json:",omitempty"`
141179

142-
// For Get requests.
180+
// For "get" requests.
143181

144182
Miss bool `json:",omitempty"` // cache miss
145-
OutputID []byte `json:",omitempty"`
146-
Size int64 `json:",omitempty"` // in bytes
147-
Time *time.Time `json:",omitempty"` // an Entry.Time; when the object was added to the docs
183+
OutputID []byte `json:",omitempty"` // the ObjectID stored with the body
184+
Size int64 `json:",omitempty"` // body size in bytes
185+
Time *time.Time `json:",omitempty"` // when the object was put in the cache (optional; used for cache expiration)
186+
187+
// For "get" and "put" requests.
148188

149-
// DiskPath is the absolute path on disk of the ObjectID corresponding
150-
// a "get" request's ActionID (on cache hit) or a "put" request's
151-
// provided ObjectID.
189+
// DiskPath is the absolute path on disk of the body corresponding to a
190+
// "get" (on cache hit) or "put" request's ActionID.
152191
DiskPath string `json:",omitempty"`
153192
}
154193

@@ -183,6 +222,8 @@ func startCacheProg(progAndArgs string, fuzzDirCache Cache) Cache {
183222
base.Fatalf("StdinPipe to GOCACHEPROG: %v", err)
184223
}
185224
cmd.Stderr = os.Stderr
225+
// On close, we cancel the context. Rather than killing the helper,
226+
// close its stdin.
186227
cmd.Cancel = in.Close
187228

188229
if err := cmd.Start(); err != nil {
@@ -435,7 +476,9 @@ func (c *ProgCache) Close() error {
435476
if c.can[cmdClose] {
436477
_, err = c.send(c.ctx, &ProgRequest{Command: cmdClose})
437478
}
479+
// Cancel the context, which will close the helper's stdin.
438480
c.ctxCancel()
481+
// Wait until the helper closes its stdout.
439482
<-c.readLoopDone
440483
return err
441484
}

0 commit comments

Comments
 (0)