OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
dnj (Google)
2016/06/09 18:00:54
nit: LUCI license (here and elsewhere)
iannucci
2016/06/15 00:45:59
Done, thanks.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // Package distributor contains all the adaptors for the various supported | |
6 // distributor protocols. At a high level, it works like this: | |
7 // * Quests specify a distributor configuration by name as part of their | |
8 // identity. | |
9 // * When an Execution for that Quest NeedsExecution, DM reads configuration | |
10 // (distributor.proto) from luci-config. This configuration is stored | |
11 // as part of the Execution so that for the duration of a given Exectuion, | |
12 // DM always interacts with the same distributor in the same way (barring | |
13 // code changes in DM's adapter logic itself). | |
14 // * DM uses the selected distributor implementation to start a task and | |
15 // record its Token. Additionally, the distributor MUST subscribe to publish | |
16 // on DM's pubsub topic for updates. When publishing updates, the | |
17 // distributor MUST include 2 attributes (execution_id, pubsub_key), which | |
18 // are provided as part of TaskDescription. | |
19 // * When DM gets a hit on pubsub, it will load the Execution, load its cached | |
20 // distributor configuration, and then call HandleNotification for the | |
21 // adapter to parse the notification body and return the state of the task. | |
22 // | |
23 // Adding a new distributor requires: | |
24 // * Add a new subdir of protos with the configuration proto for the new | |
25 // distributor. Each distributor implementation must have its own unique | |
26 // Config message. | |
27 // * Add a matching subdir of this package for the implementation of the | |
28 // distributor. | |
29 // * In the implementation, add a Register method that registers the | |
30 // implementation with this package appropriately. | |
31 // * In the DM frontend, import your new package implementation and run its | |
32 // Register method. | |
33 package distributor | |
34 | |
35 import ( | |
36 "net/http" | |
37 "time" | |
38 | |
39 dm "github.com/luci/luci-go/common/api/dm/service/v1" | |
40 | |
41 "golang.org/x/net/context" | |
42 ) | |
43 | |
44 // Token is an opaque token that a distributor should use to | |
45 // uniquely identify a single DM execution. | |
46 type Token string | |
47 | |
48 // The PersistentState token for the job. For a given Attempt, this will be | |
49 // retrieved from Finished executions and then passed to new Executions. | |
50 type PersistentState string | |
51 | |
52 // TaskResult is the conclusion of the task. One of the two fields may be | |
53 // populated. | |
54 type TaskResult struct { | |
55 // If AbnormalFinish is nil, the Execution is counted as FINISHED, with this | |
56 // value as its PersistentState. | |
57 PersistentState PersistentState | |
dnj (Google)
2016/06/09 18:00:54
nit: "If PersistentState"
iannucci
2016/06/15 00:45:59
Done.
| |
58 // If this is !nil, the Exectuion is counted as ABNORMAL_FINISHED, with this | |
59 // value as the result. | |
60 AbnormalFinish *dm.AbnormalFinish | |
61 } | |
62 | |
63 // Notification represents a notification from the distributor to DM that | |
64 // a particular execution has a status update. Data and Attrs are interpreted | |
65 // purely by the distributor implementation. | |
66 type Notification struct { | |
67 ID *dm.Execution_ID | |
68 Data []byte | |
69 Attrs map[string]string | |
70 } | |
71 | |
72 // D is the interface for all distributor implementations. | |
73 // | |
74 // Retries | |
75 // | |
76 // Unless otherwise noted, DM will retry methods here if they return an error | |
77 // marked as Transient, up to some internal limit. If they return | |
78 // a non-Transient error (or nil) DM will make a best effort not to duplicate | |
79 // calls, but it can't guarantee that. | |
80 type D interface { | |
81 // Run prepares and runs a new Task from the given TaskDescription. | |
82 // | |
83 // Scheduling the same TaskDescription multiple times SHOULD return the same | |
84 // Token. It's OK if this doesn't happen, but only one of the scheduled tasks | |
85 // will be able to invoke ActivateExecution; the other one(s) will | |
86 // early-abort and/or timeout. | |
87 // | |
88 // If this returns a non-Transient error, the Execution will be marked a s | |
89 // Rejected with the returned error message as the 'Reason'. | |
90 // | |
91 // The various time durations, if non-zero, will be used verbatim for DM to | |
92 // timeout that phase of the task's execution. If the task's execution t imes | |
93 // out in the 'STOPPING' phase, DM will poll the distributor's GetStatus | |
94 // method up to 3 times with a 30-second gap to attempt to retrieve the final | |
95 // information. After more than 3 times, DM will give up and mark the ta sk as | |
96 // expired. | |
97 // | |
98 // If the distributor doesn't intend to use Pubsub for notifying DM abou t the | |
99 // final status of the job, set timeToStop to the amount of time you wan t DM | |
100 // to wait before polling GetStatus. e.g. if after calling FinishAttempt or | |
101 // EnsureGraphData your distributor needs 10 seconds before it can corre ctly | |
102 // respond to a GetStatus request, you should set timeToStop to >= 10s. | |
103 // Otherwise timeToStop should be set fairly high as a hedge against a b roken | |
104 // pubsub notification pipeline. | |
dnj (Google)
2016/06/09 18:00:54
Maybe mention that delays over 10s have occasional
iannucci
2016/06/15 00:45:58
Done.
| |
105 // | |
106 // If you have the choice between pubsub or not, prefer to use pubsub as it | |
107 // allows DM to more proactively update the graph state (and unblock wai ting | |
108 // Attempts, etc.) | |
109 Run(*TaskDescription) (tok Token, timeToStart, timeToRun, timeToStop tim e.Duration, err error) | |
110 | |
111 // Cancel attempts to cancel a running task. If a task is canceled more than | |
112 // once, this should return nil. | |
113 Cancel(Token) error | |
114 | |
115 // GetStatus retrieves the current state of the task from the distributo r. | |
116 // | |
117 // If this returns a non-Transient error more than 30 seconds after the task | |
118 // was Run(), the execution will be marked Missing with the returned err or | |
119 // message as the 'Reason'. If it returns a non-Transient error within 3 0 | |
120 // seconds of being run, DM will automatically treat that as Transient. | |
121 GetStatus(Token) (*TaskResult, error) | |
122 | |
123 // InfoURL calculates a user-presentable information url for the task | |
124 // identified by Token. This should be a local operation, so it is not t he | |
125 // implementation's responsibility to validate the token in this method (e.g. | |
126 // it could point to a non-existant job, etc.) | |
127 InfoURL(Token) string | |
128 | |
129 // HandleNotification is called whenever DM receives a PubSub message se nt to | |
130 // a topic created with TaskDescription.PrepareTopic. The Attrs map will omit | |
131 // the 'auth_token' field. | |
132 // | |
133 // Returning (nil, nil) will indicate that DM should ignore this notific ation. | |
134 // | |
135 // DM will convert pubsub Messages to a delayed GetStatus if a pubsub me ssage | |
136 // is delivered which refers to an Attempt whose status is NeedsExecutio n, | |
137 // which could happen in the event of a not-fully-settled transacion. | |
138 // | |
139 // DM will ignore any notifications for executions which it doesn't know | |
140 // about. | |
141 HandleNotification(notification *Notification) (*TaskResult, error) | |
142 | |
143 // HandleTaskQueueTask is called if the distributor used Config.EnqueueT ask. | |
144 // | |
145 // It may return zero or more Notifications for DM about arbitrary Execu tions. | |
146 // These notifications will be handled 'later' by the HandleNotification | |
147 // implementation. | |
148 HandleTaskQueueTask(r *http.Request) ([]*Notification, error) | |
149 | |
150 // Validate should return a non-nil error if the given payload is not | |
151 // appropriate for this Distributor. Payload is guaranteed to be a valid | |
152 // json object. This should validate that the content of that json objec t is | |
dnj (Google)
2016/06/09 18:00:54
nit: JSON
iannucci
2016/06/15 00:45:59
Done.
| |
153 // what the distributor expects. | |
154 Validate(payload string) error | |
155 } | |
156 | |
157 // Factory is a function which produces new distributor instance with the | |
158 // provided configuration proto. | |
159 // | |
160 // c is guaranteed to be non-transactional. | |
161 type Factory func(c context.Context, dist *Config) (D, error) | |
OLD | NEW |