-
Notifications
You must be signed in to change notification settings - Fork 874
feat(agent/agentcontainers): add file watcher and dirty status #17573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
40c8de9
a997f82
0e568fb
4f788d9
bfeb1da
45a978c
d2721a7
c03bb7d
aed7c30
39526e6
7edee90
9cf5415
de2a42e
0cbee38
5ced7e1
5a96a55
0b16448
eaf5922
617fed2
8ee9914
263c683
58a70e8
9f739ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,12 +45,12 @@ type API struct { | |
|
||
// lockCh protects the below fields. We use a channel instead of a | ||
// mutex so we can handle cancellation properly. | ||
lockCh chan struct{} | ||
containers codersdk.WorkspaceAgentListContainersResponse | ||
mtime time.Time | ||
devcontainerNames map[string]struct{} // Track devcontainer names to avoid duplicates. | ||
knownDevcontainers []codersdk.WorkspaceAgentDevcontainer // Track predefined and runtime-detected devcontainers. | ||
configModifiedTimes map[string]time.Time // Track when config files were last modified. | ||
lockCh chan struct{} | ||
containers codersdk.WorkspaceAgentListContainersResponse | ||
mtime time.Time | ||
devcontainerNames map[string]struct{} // Track devcontainer names to avoid duplicates. | ||
knownDevcontainers []codersdk.WorkspaceAgentDevcontainer // Track predefined and runtime-detected devcontainers. | ||
configFileModifiedTimes map[string]time.Time // Track when config files were last modified. | ||
} | ||
|
||
// Option is a functional option for API. | ||
|
@@ -108,16 +108,16 @@ func WithWatcher(w watcher.Watcher) Option { | |
func NewAPI(logger slog.Logger, options ...Option) *API { | ||
ctx, cancel := context.WithCancel(context.Background()) | ||
api := &API{ | ||
ctx: ctx, | ||
cancel: cancel, | ||
done: make(chan struct{}), | ||
logger: logger, | ||
clock: quartz.NewReal(), | ||
cacheDuration: defaultGetContainersCacheDuration, | ||
lockCh: make(chan struct{}, 1), | ||
devcontainerNames: make(map[string]struct{}), | ||
knownDevcontainers: []codersdk.WorkspaceAgentDevcontainer{}, | ||
configModifiedTimes: make(map[string]time.Time), | ||
ctx: ctx, | ||
cancel: cancel, | ||
done: make(chan struct{}), | ||
logger: logger, | ||
clock: quartz.NewReal(), | ||
cacheDuration: defaultGetContainersCacheDuration, | ||
lockCh: make(chan struct{}, 1), | ||
devcontainerNames: make(map[string]struct{}), | ||
knownDevcontainers: []codersdk.WorkspaceAgentDevcontainer{}, | ||
configFileModifiedTimes: make(map[string]time.Time), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is fine for now, but if we ever decide to expose this in the API we may want to refactor this to a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure we need to store a null time in the map, that can already be represented by missing map entry or zero time. But if we expose it in |
||
} | ||
for _, opt := range options { | ||
opt(api) | ||
|
@@ -281,7 +281,7 @@ func (api *API) getContainers(ctx context.Context) (codersdk.WorkspaceAgentListC | |
// Check if this container was created after the config | ||
// file was modified. | ||
if configFile != "" && api.knownDevcontainers[knownIndex].Dirty { | ||
lastModified, hasModTime := api.configModifiedTimes[configFile] | ||
lastModified, hasModTime := api.configFileModifiedTimes[configFile] | ||
if hasModTime && container.CreatedAt.After(lastModified) { | ||
api.logger.Info(ctx, "clearing dirty flag for container created after config modification", | ||
slog.F("container", container.ID), | ||
|
@@ -316,7 +316,7 @@ func (api *API) getContainers(ctx context.Context) (codersdk.WorkspaceAgentListC | |
|
||
dirty := dirtyStates[workspaceFolder] | ||
if dirty { | ||
lastModified, hasModTime := api.configModifiedTimes[configFile] | ||
lastModified, hasModTime := api.configFileModifiedTimes[configFile] | ||
if hasModTime && container.CreatedAt.After(lastModified) { | ||
api.logger.Info(ctx, "new container created after config modification, not marking as dirty", | ||
slog.F("container", container.ID), | ||
|
@@ -473,7 +473,7 @@ func (api *API) markDevcontainerDirty(configPath string, modifiedAt time.Time) { | |
} | ||
|
||
// Record the timestamp of when this configuration file was modified. | ||
api.configModifiedTimes[configPath] = modifiedAt | ||
api.configFileModifiedTimes[configPath] = modifiedAt | ||
|
||
for i := range api.knownDevcontainers { | ||
if api.knownDevcontainers[i].ConfigPath == configPath { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review: This change allows all
r.Context
s to inherit the graceful context from the agent, ensuring cancellation on agent shutdown.