appuio / cloud-portal

APPUiO Cloud Portal (Web Frontend)
Apache License 2.0
5 stars 0 forks source link

Implement watching resources #532

Open ccremer opened 1 year ago

ccremer commented 1 year ago

Summary

As user\ I want to watch Kubernetes resources\ So that changed Kubernetes objects are displayed immediately without complicated cache invalidation.

Context

Currently, we use Memoization when querying Kubernetes resources (since PR #482). This means that the Portal maintains a state for performance reasons. For example, upon loading /organizations the Portal fetches all Organizations from the API only once initially. After that, every time when the user visits /organizations again, the result is returned from in-browser-memory.

This results in a faster UX, but has one big drawback: Cache invalidation. The user could miss a change that someone else did since the resources were initially loaded. We assume that resources in APPUiO Cloud change rarely. Granted, the resources can be re-fetched anytime upon full browser page reload, but there could be an even better way by using Kubernetes' watch feature.

Another problem is conflicts when updating. Imagine Alice and Bob load all Organizations at the same time. Bob changes the display name of an organization and saves it. Alice, a minute later, also edits the same Organization and tries to save it. Kubernetes denies the change since Bob already updated it and Alice tries to update an outdated resource. Presumably this rarely happens, but it can happen.

With this feature implemented,

Out of Scope

Further links

Acceptance Criteria

Scenario Outline: Notify when editing
  Given 2 users Alice and Bob
  And both have loaded the <entity> to state/cache
  And both edit the same <entity>
  When Bob saves the changes to <entity> before Alice
  Then Alice gets a toast notification that <entity> has been changed on the server.

  Scenarios:
    | <entity>
    | Organization
    | Team
    | OrganizationMembers
Scenario Outline: Update when listing
  Given <entity> is loaded in state/cache
  When a 3rd-party updates <entity> in Kubernetes
  Then the list of <entity> in Alice's gets re-rendered with the updated <entity>

  Scenarios:
    | <entity>
    | Organization
    | Team
    | OrganizationMembers

Implementation Ideas

Since Angular doesn't support streaming, we have to use the native API, e.g. fetch. Parsing the updates from watches is one thing, but we shouldn't forget about aborting watches, e.g. upon page navigation.

A blogpost explains how fetch requests can be canceled using an AbortController.

Currently, the Portal uses the KubernetesCollectionService as a generic abstraction to fetch and update resources from/in Kubernetes. This class could be extended to support watch requests, that internally updates the state resp. cache for its internal subscribers.

Also, if Kubernetes pushes changes of a resource that the user is currently editing, we can notify the user to reload the latest changes before submitting.