@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
JavaScript
// 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;
}
}