Skip to content

Conversation

@szaimen
Copy link
Collaborator

@szaimen szaimen commented Jan 19, 2026

@szaimen szaimen added this to the next milestone Jan 19, 2026
@szaimen szaimen added 2. developing Work in progress enhancement New feature or request labels Jan 19, 2026
Copy link
Collaborator

@asavageiv asavageiv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good so far, just a few comments.

});
serverSentEventSource.onerror = function() { serverSentEventSource.close(); };
} catch (connectionError) {
/* ignore if Server-Sent Events are not available */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we log something in case there is another unexpected source of an exception?

$eventJson = json_encode($payload);

// Append new event (atomic via LOCK_EX)
file_put_contents($eventsFile, $eventJson . PHP_EOL, FILE_APPEND | LOCK_EX);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work? Is $eventsFile in scope?

return;
}

// Emit a container-start event for frontend clients (one JSON line per event)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think DockerController is starting to have too many direct responsibilities. It already mixes the logic for container lifecycle with HTTP request/response handling and this adds ContainerEvents too. How about we create a ContainerEventLog class and encapsulate the file management there? I imagine an API like emitEvent and open, readNextEvent, close would be easy from where this is now.

error_log('Could not write container-start event: ' . $e->getMessage());
}

$this->dockerActionManager->DeleteContainer($container);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is out of scope, but the fact that there are so many calls in a row to dockerActionManager here make it smell like this function should be moved into the DockerActionManager. WDYT? Would you accept a PR?

Generally, I would slowly move towards DockerController focusing on handling HTTP requests and responses and calling into deeper layers for the logic of the requests. The handling would start to all look like:

  1. read the request
  2. call a method or two to make it happen
  3. write back the response with the results

}

public function StreamContainerEvents(Response $response): Response {
$eventsFile = \AIO\Data\DataConst::GetContainerEventsFile();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be moved next to the fopen or does it have to happen before setting the headers?

// Attempt to connect to Server-Sent Events at /events/containers and listen for 'container-start' events
if (typeof EventSource !== 'undefined') {
try {
const serverSentEventSource = new EventSource('events/containers');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://developer.mozilla.org/en-US/docs/Web/API/EventSource says that this has significant limitations when used over HTTP1. Are we concerned about that at all?

Copy link
Collaborator Author

@szaimen szaimen Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We disallow multiple tabs so that should not be a problem but we should probably add a check here as well to abort any connection attempt if a second tab was opened like done here:

channel.addEventListener('message', (msg) => {

// Start at end of file so only new events are streamed
fseek($fileHandle, 0, SEEK_END);

while (!connection_aborted()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the good case where all the containers start, will the connection abort?

if ($line !== false) {
$data = trim($line);
// Write SSE event
$body->write("event: container-start\n");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating a ContainerEvent class would also abstract the fact that right now these are only 'start' events.

->withHeader('Connection', 'keep-alive');

$fileHandle = fopen($eventsFile, 'r');
if ($fileHandle === false) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably log an error if this happens since we try and create the file above. Something's configured wrong if this failed.

Signed-off-by: Simon L. <szaimen@e.mail.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2. developing Work in progress enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants