ModelPermissionFetcher.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { DeferredPromise } from "@common/DeferredPromise";
  2. import { forEachIn } from "@common/utils/forEachIn";
  3. import { useWebsocketStore } from "./stores/websocket";
  4. export interface ModelPermissionFetcherRequest {
  5. promise: DeferredPromise;
  6. payload: {
  7. modelName: string;
  8. modelId: string;
  9. };
  10. }
  11. /**
  12. * Class used for fetching model permissions in bulk, every 25ms max
  13. * So if there's 200 models loaded, it would do only 1 request to fetch model permissions, not 200 separate ones
  14. */
  15. export class ModelPermissionFetcher {
  16. private static requestsQueued: ModelPermissionFetcherRequest[] = [];
  17. private static timeoutActive = false;
  18. private static fetch() {
  19. // If there is no other timeout running, indicate we will run one. Otherwise, return, as a timeout is already running
  20. if (!this.timeoutActive) this.timeoutActive = true;
  21. else return;
  22. setTimeout(() => {
  23. // Reset timeout active, so another one can run
  24. this.timeoutActive = false;
  25. // Make a copy of all requests currently queued, and then take those requests out of the queue so we can request them
  26. const requests = this.requestsQueued;
  27. this.requestsQueued = [];
  28. // Splits the requests per model
  29. const requestsPerModel = {};
  30. requests.forEach(request => {
  31. const { modelName } = request.payload;
  32. if (!Array.isArray(requestsPerModel[modelName]))
  33. requestsPerModel[modelName] = [];
  34. requestsPerModel[modelName].push(request);
  35. });
  36. const modelNames = Object.keys(requestsPerModel);
  37. const { runJob } = useWebsocketStore();
  38. // Runs the requests per model
  39. forEachIn(modelNames, async modelName => {
  40. // Gets a unique list of all model ids for the current model that we want to request permissions for
  41. const modelIds = Array.from(
  42. new Set(
  43. requestsPerModel[modelName].map(
  44. request => request.payload.modelId
  45. )
  46. )
  47. );
  48. const result = await runJob("data.users.getModelPermissions", {
  49. modelName,
  50. modelIds
  51. });
  52. const requests = requestsPerModel[modelName];
  53. // For all requests, resolve the deferred promise with the returned permissions for the model that request requested
  54. requests.forEach(request => {
  55. const { payload, promise } = request;
  56. const { modelId } = payload;
  57. promise.resolve(result[modelId]);
  58. });
  59. });
  60. }, 25);
  61. }
  62. public static fetchModelPermissions(modelName, modelId) {
  63. return new Promise(resolve => {
  64. const promise = new DeferredPromise();
  65. // Listens for the deferred promise response, before we actually push and fetch
  66. promise.promise.then(result => {
  67. resolve(result);
  68. });
  69. // Pushes the request to the queue
  70. this.requestsQueued.push({
  71. payload: {
  72. modelName,
  73. modelId
  74. },
  75. promise
  76. });
  77. // Calls the fetch function, which will start a timeout if one isn't already running, which will actually request the permissions
  78. this.fetch();
  79. });
  80. }
  81. }