models.svelte.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import * as modelsApi from '$lib/api/models';
  2. import { notificationsStore } from '$lib/stores/notifications.svelte';
  3. import { ResourceStore } from '$lib/stores/resources.svelte';
  4. import type { ExternalModelCR, ManagedModelCR } from '$lib/types/custom-resources';
  5. import type { DeploymentStatus, ExternalModelStatus, Model } from '$lib/types/entities';
  6. type CRCondition = { type: string; status: 'True' | 'False' | 'Unknown' };
  7. const readyCondition = (conditions: CRCondition[]) =>
  8. conditions.find((c) => c.type === 'Ready')?.status;
  9. const managedStatusFromCR = (status: ManagedModelCR['status']): DeploymentStatus => {
  10. if (!status || typeof status !== 'object') return 'not-deployed';
  11. const ready = readyCondition(status.conditions ?? []);
  12. if (ready === 'True') return 'running';
  13. if (ready === 'False') return 'degraded';
  14. return 'pending';
  15. };
  16. const externalStatusFromCR = (
  17. status: ExternalModelCR['status'],
  18. ): ExternalModelStatus | undefined => {
  19. if (!status || typeof status !== 'object') return undefined;
  20. const ready = readyCondition(status.conditions ?? []);
  21. if (ready === 'True') return 'available';
  22. if (ready === 'False') return 'error';
  23. return undefined;
  24. };
  25. type CRStatus = ManagedModelCR['status'] | ExternalModelCR['status'];
  26. class ModelsStore extends ResourceStore<Model, CRStatus> {
  27. constructor() {
  28. super('Model', [
  29. {
  30. group: 'locostack.com',
  31. version: 'v1alpha1',
  32. resources: 'managedmodels',
  33. },
  34. {
  35. group: 'locostack.com',
  36. version: 'v1alpha1',
  37. resources: 'externalmodels',
  38. },
  39. ]);
  40. }
  41. protected resourceHref(id: string) {
  42. return `/workloads/models/${id}`;
  43. }
  44. protected apiGet(workspaceId: string, id: string) {
  45. return modelsApi.get(workspaceId, id);
  46. }
  47. protected apiGetStatus(workspaceId: string, id: string) {
  48. return modelsApi.getStatus(workspaceId, id);
  49. }
  50. protected apiCreate(workspaceId: string, model: Model) {
  51. return modelsApi.create(workspaceId, model);
  52. }
  53. protected apiUpdate(workspaceId: string, model: Model) {
  54. return modelsApi.update(workspaceId, model);
  55. }
  56. protected apiDelete(workspaceId: string, id: string) {
  57. return modelsApi.remove(workspaceId, id);
  58. }
  59. protected onStatusChange(id: string, status: CRStatus, notify = true): void {
  60. const item = this.get(id);
  61. if (!item) return;
  62. let newStatus: string | undefined;
  63. if (item.mode === 'managed') {
  64. const managedStatus = managedStatusFromCR(status as ManagedModelCR['status']);
  65. if (item.status !== managedStatus) {
  66. newStatus = managedStatus;
  67. item.status = managedStatus;
  68. }
  69. } else if (item.mode === 'external') {
  70. const externalStatus = externalStatusFromCR(status as ExternalModelCR['status']);
  71. if (item.status !== externalStatus) {
  72. newStatus = externalStatus;
  73. item.status = externalStatus;
  74. }
  75. }
  76. if (notify && newStatus !== undefined) {
  77. this.#notifyStatusChange(id, item.name, newStatus);
  78. }
  79. }
  80. #notifyStatusChange(id: string, name: string, status: string): void {
  81. const href = this.resourceHref(id);
  82. notificationsStore.push({
  83. type: 'success',
  84. message: `Model "${name}" is now ${status}`,
  85. href,
  86. });
  87. }
  88. }
  89. const modelsStore = new ModelsStore();
  90. export { modelsStore };