UNPKG

@golemcloud/golem-ts

Version:

A library that help writing Golem programs by providing higher level wrappers for Golem's runtime APIs, including functions for defining and performing operations transactionally.

190 lines (189 loc) 6.16 kB
// Copyright 2024-2025 Golem Cloud // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { getIdempotenceMode, getOplogPersistenceLevel, getRetryPolicy, markBeginOperation, markEndOperation, setIdempotenceMode, setOplogPersistenceLevel, setRetryPolicy, } from "./hostapi"; /** * PersistenceLevelGuard is a guard type that sets the persistence level for the oplog. * You must call drop on the guard once you are finished using it. */ export class PersistenceLevelGuard { constructor(originalLevel) { this.originalLevel = originalLevel; } drop() { setOplogPersistenceLevel(this.originalLevel); } } /** * Sets the persistence level for the oplog and returns a guard. * You must call drop on the guard once you are finished using it. * @param level - The persistence level to set. * @returns A PersistenceLevelGuard instance. */ export function usePersistenceLevel(level) { const originalLevel = getOplogPersistenceLevel(); setOplogPersistenceLevel(level); return new PersistenceLevelGuard(originalLevel); } /** * Executes a function with a specific persistence level for the oplog. * @param level - The persistence level to set. * @param f - The function to execute. * @returns The result of the executed function. */ export function withPersistenceLevel(level, f) { const guard = usePersistenceLevel(level); return executeWithDrop([guard], f); } /** * IdempotenceModeGuard is a guard type that sets the idempotence mode. * You must call drop on the guard once you are finished using it. */ export class IdempotenceModeGuard { constructor(original) { this.original = original; } drop() { setIdempotenceMode(this.original); } } /** * Sets the idempotence mode and returns a guard. * You must call drop on the guard once you are finished using it. * @param mode - The idempotence mode to set. * @returns An IdempotenceModeGuard instance. */ export function useIdempotenceMode(mode) { const original = getIdempotenceMode(); setIdempotenceMode(mode); return new IdempotenceModeGuard(original); } /** * Executes a function with a specific idempotence mode. * @param mode - The idempotence mode to set. * @param f - The function to execute. * @returns The result of the executed function. */ export function withIdempotenceMode(mode, f) { const guard = useIdempotenceMode(mode); return executeWithDrop([guard], f); } /** * RetryPolicyGuard is a guard type that sets the retry policy. * You must call drop on the guard once you are finished using it. */ export class RetryPolicyGuard { constructor(original) { this.original = original; } drop() { setRetryPolicy(this.original); } } /** * Sets the retry policy and returns a guard. * You must call drop on the guard once you are finished using it. * @param policy - The retry policy to set. * @returns A RetryPolicyGuard instance. */ export function useRetryPolicy(policy) { const original = getRetryPolicy(); setRetryPolicy(policy); return new RetryPolicyGuard(original); } /** * Executes a function with a specific retry policy. * @param policy - The retry policy to set. * @param f - The function to execute. * @returns The result of the executed function. */ export function withRetryPolicy(policy, f) { const guard = useRetryPolicy(policy); return executeWithDrop([guard], f); } /** * AtomicOperationGuard is a guard type that marks the beginning and end of an atomic operation. * You must call drop on the guard once you are finished using it. */ export class AtomicOperationGuard { constructor(begin) { this.begin = begin; } drop() { markEndOperation(this.begin); } } /** * Marks the beginning of an atomic operation and returns a guard. * You must call drop on the guard once you are finished using it. * @returns An AtomicOperationGuard instance. */ export function markAtomicOperation() { const begin = markBeginOperation(); return new AtomicOperationGuard(begin); } /** * Executes a function atomically. * @param f - The function to execute atomically. * @returns The result of the executed function. */ export function atomically(f) { const guard = markAtomicOperation(); return executeWithDrop([guard], f); } /** * Executes a function and automatically drops the provided resources after execution. * @param resources - An array of resources to be dropped after execution. * @param fn - The function to execute. * @returns The result of the executed function. */ export function executeWithDrop(resources, fn) { try { const result = fn(); dropAll(true, resources); return result; } catch (e) { dropAll(false, resources); throw e; } } /** * Drops all the provided resources and collects any errors that occur during the process. * @param resources - An array of resources to be dropped. * @throws DropError if any errors occur during the dropping process. */ export function dropAll(throwOnError, resources) { const errors = []; for (const resource of resources) { try { resource.drop(); } catch (e) { errors.push(e); } } if (throwOnError && errors.length > 0) { throw new DropError(errors); } } /** * Custom error class for errors that occur during the dropping of resources. */ class DropError extends Error { constructor(errors) { const message = errors.map((e) => e.message).join(", "); super(`Error dropping resources: ${message}`); this.errors = errors; } }