
Research
/Security News
Weaponizing Discord for Command and Control Across npm, PyPI, and RubyGems.org
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
@evermind-sh/sdk
Advanced tools
Evermind, translated from the Rohanese word Simbelmynë—the name of a small white flower symbolizing "everlasting memory"—is a simple, reliable, and scalable Distributed Lock-as-a-Service (LaaS).
Locks (sometimes referred to as a Mutex or a Semaphore) empowers developers to maintain consistency across distributed systems effortlessly by offering tools to acquire, extend, and release locks on shared resources.
Evermind simplifies complex coordination challenges, enabling robust, fault-tolerant applications that ensure atomic operations on resources across distributed systems.
Evermind eliminates the complexities of building and managing distributed locking mechanisms. Our service provides:
Evermind is billed based on how much usage (i.e. how many locks you will be acquiring), based on Lock Acquisition Attempts (LAAs).
A Lock Acquisition Attempt (LAA) is where a call to the Evermind Lock API attempts to acquire a lock on a resource, if that resource can be acquired on the first attempt and then a subsequent call to the Evermind API releases it, that is 1 LAA.
If that resource is unable to be acquired on the first attempt and must retry N
times then the total number of LAAs used would be M
, where M
is 1 + the number of retires
.
Lock Acquisition Attempts approximately measure usage in the system, although notably Lock Releases and Lock extensions are not billed and do not count towards your Licence Key usage.
Check our the pricing plans and subscribe via our storefront.
In the future Evermind will offer Pay as you go pricing, currently you must sign up for a subscription.
Need unlimited LAAs or a higher level of support/isolation? Reach out to hello@evermind.sh!
To interact with Evermind's lock API, you first need to exchange your Polar.sh license key for an API key. Licence Keys can be purchased from our Polar.sh storefront.
Licence Keys are automatically managed by Polar and will expire and have their usage allocations tracked within the Polar system, but you manage your own API Keys.
There is a 1:M relationship between Licence Keys and API Keys, all API Keys created for a Licence Key will contribute to that Licence Keys usage allocation.
Install the CLI globally:
npm install -g evermind
Or, run the command using npx
, bunx
, etc.
Create an API key:
npx evermind keys create --licenceKey <licence-key>
Or let the Evermind CLI read the licence key from the EVERMIND_LICENCE_KEY
environment variable:
export EVERMIND_LICENCE_KEY=YOUR_POLAR_SH_LICENCE_KEY
npx evermind keys create
Delete an API key:
npx evermind keys delete YOUR_API_KEY --licenceKey YOUR_POLAR_SH_LICENCE_KEY
Or use an environment variable:
export EVERMIND_LICENCE_KEY=YOUR_POLAR_SH_LICENCE_KEY
npx evermind keys delete YOUR_API_KEY
https://api.evermind.sh/api-key
POST
{
"licenceKey": "YOUR_POLAR_SH_LICENCE_KEY"
}
{
"apiKey": "YOUR_API_KEY"
}
cURL Example:
curl -X POST https://api.evermind.sh/api-key \
-H "Content-Type: application/json" \
-d '{
"licenceKey": "YOUR_POLAR_SH_LICENCE_KEY"
}'
https://api.evermind.sh/api-key
DELETE
{
"licenceKey": "YOUR_POLAR_SH_LICENCE_KEY",
"apiKey": "YOUR_API_KEY"
}
cURL Example:
curl -X DELETE https://api.evermind.sh/api-key \
-H "Content-Type: application/json" \
-d '{
"licenceKey": "YOUR_POLAR_SH_LICENCE_KEY",
"apiKey": "YOUR_API_KEY"
}'
Once you have an API key, you can interact with the lock service to acquire, extend, and release locks. The following sections describe how to use the system directly via HTTP methods and with the TypeScript SDK.
Install the SDK:
npm
npm install @evermind/sdk
Example Usage:
import { Evermind } from 'evermind';
const evermind = new Evermind({ apiKey: 'YOUR_API_KEY' });
const key = 'my_resource';
// Acquire a lock directly
const acquireResponse = await evermind.acquire({ key, lease: 5000 });
console.log('Acquire:', acquireResponse);
// Extend a lock that has been acquired
if (acquireResponse.acquired) {
const extendResponse = await evermind.extend({ key, uuid: acquireResponse.config.uuid, extendBy: 2000 });
console.log('Extend:', extendResponse);
// Release the lock
const releaseResponse = await evermind.release({ key, uuid: acquireResponse.config.uuid, softFail: true });
console.log('Release:', releaseResponse);
}
// Using `withLock` to simplify lock management, will automatically release the lock once the routine is finished.
const result = await evermind.withLock({ key }, async () => {
// Do some work while holding the lock
return 'some result';
});
https://lock.evermind.sh/lock/acquire
POST
{
"key": "<your resource key>",
"lease": 5000,
"retryAttempts": 5,
"retryDelay": 500
}
{
"acquired": true,
"lockAcquisitionAttempts": 1,
"config": {
"key": "<your resource key>",
"lease": 5000,
"retryAttempts": 5,
"retryDelay": 500,
"uuid": "<UUIDv7>"
},
"message": null
}
cURL Example:
curl -X POST https://lock.evermind.sh/lock/acquire \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"key": "<your resource key>",
"lease": 5000,
"retryAttempts": 5,
"retryDelay": 500
}'
https://lock.evermind.sh/lock/extend
POST
{
"key": "<your resource key>",
"uuid": "<UUIDv7>",
"extendBy": 3000,
"softFail": true
}
{
"extended": true,
"message": null
}
cURL Example:
curl -X POST https://lock.evermind.sh/lock/extend \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"key": "<your resource key>",
"extendBy": 3000,
"uuid": "<UUIDv7>"
}'
https://lock.evermind.sh/lock/release
POST
{
"key": "<your resource key>",
"uuid": "<UUIDv7>",
"softFail": true
}
{
"released": true,
"message": null
}
cURL Example:
curl -X POST https://lock.evermind.sh/lock/release \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"key": "<your resource key>",
"uuid": "<UUIDv7>"
}'
Here’s the expanded DTOs section with endpoint details, Evermind SDK method names, descriptions, caveats, and additional explanations.
The Lock API is used for acquiring, extending, and releasing locks. Below are the DTOs for each operation, along with their corresponding HTTP endpoints and Evermind SDK method names.
The resulting Resource Key (the globally unique key to acquire the lock on) is in the following format.
<GlobalPrefix>:<IdentityId>:<Key>
GlobalPrefix
: Will always be Evermind
unless you have your own deployment or isolated environment of the Evermind system. This key will be the same across all locks in the system.IdentityId
: A unique ID that corresponds to the account that the API key belongs to, if purchased via the Polar.sh storefront this will be your userId
.Key
: The key you pass in for the resource, this can be anything you want it to be.The only parts you have control over are the Key
, the other parts of the lock key are managed by the system itself and are there to prevent locks from clashing across users of Evermind.
Field | Type | Required | Description |
---|---|---|---|
key | string | Yes | The resource to acquire a lock on. |
lease | number | No | Lock duration in milliseconds. Default: 10000 . |
retryAttempts | number | No | Number of retry attempts. Default: 10 . |
retryDelay | number | No | Milliseconds between retries. Default: 500 . |
retryJitter | number | No | An amount of time in milliseconds to randomly add to the retry delay to help in times of high lock contention. See: https://www.awsarchitectureblog.com/2015/03/backoff.html. Default: 0 . |
uuid | string | No | Optional custom UUID for the lock. If not provided a UUIDv7 is used by default. It is recommended you use the default. |
softFail | boolean | No | Return errors inline in an HTTP 200 instead of throwing errors. |
fifo | boolean | No | Whether this lock should be acquired in FIFO or FCFS order. |
POST https://lock.evermind.sh/lock/acquire
evermind.acquire(options: AcquireOptions)
Description:
Acquires a lock on a given resource (key
). By default, if the lock cannot be acquired immediately, the system will retry the specified number of times (retryAttempts
) with the provided delay (retryDelay
).
Caveats:
uuid
. If a custom UUID is not provided, the system generates one.softFail: true
ensures errors are returned inline instead of throwing exceptions. This can simplify error handling in some scenarios.fifo
value otherwise locks may get into an unrecoverable state since some will be trying to acquire in FIFO order and some in FCFS order.Field | Type | Required | Description |
---|---|---|---|
key | string | Yes | The resource key to extend the lock on. |
uuid | string | Yes | UUID (or custom value) of the lock acquisition to extend. |
extendBy | number | Yes | Milliseconds to extend the lock. |
softFail | boolean | No | Return errors inline in an HTTP 200 instead of throwing errors. |
POST https://lock.evermind.sh/lock/extend
evermind.extend(options: ExtendOptions)
Description:
Extends the duration of an existing lock. The uuid
must match the UUID of the currently held lock, and the extendBy
value specifies how much additional time (in milliseconds) to add to the lock duration.
Caveats:
softFail
is set to true
.Field | Type | Required | Description |
---|---|---|---|
key | string | Yes | The resource key to release the lock on. |
uuid | string | Yes | UUID (or custom value) of the lock acquisition to release. |
softFail | boolean | No | Return errors inline in an HTTP 200 instead of throwing errors. |
POST https://lock.evermind.sh/lock/release
evermind.release(options: ReleaseOptions)
Description:
Releases a lock on a resource. The uuid
must match the UUID used to acquire the lock. If the lock is already released or does not exist, the response will indicate this unless softFail
is set to true
.
Caveats:
uuid
provided matches the one used during acquisition; otherwise, the release will fail.softFail: true
can help avoid exceptions when the lock does not exist or has already been released.Operation | HTTP Endpoint | SDK Method | Description |
---|---|---|---|
Acquire Lock | POST /lock/acquire | evermind.acquire | Attempts to acquire a lock on the given resource. |
Extend Lock | POST /lock/extend | evermind.extend | Extends the duration of a held lock. |
Release Lock | POST /lock/release | evermind.release | Releases the lock on the specified resource. |
softFail: true
in any request results in errors being returned inline within a 200 OK
response.Evermind offers a managed DLaaS solution. However, various alternatives exist for concurrency control. Here's a comparison to help you choose the right tool:
sync.Mutex
(Go), asyncio.Lock
(Python), and @synchronized
(Objective-C/Swift) operate within a single process's memory.redlock
): Fault-tolerant distributed locking using multiple Redis instances. However, managing Redis infrastructure introduces additional complexity.Evermind.sh is hosted on Fly.io and has servers in the following regions:
yyz
- Toronto, Canadayul
- Montreal, Canadasea
- Seattle, Washington (US)If you are wanting to use Evermind in a region closer to where your servers are going to be, feel free to open a pull request here with your new region request. You can find the available regions here.
You can choose to send your traffic to a specific region using this method. Only the regions above are supported.
If you are looking for your own deployment on infrastructure isolated from the rest of the Evermind platform or are wanting to run all services (Lock API, Database and Cache) in the same region as the server, feel free to reach out to hello@evermind.sh.
0.10.2 (2024-12-07)
This was a version bump only, there were no code changes.
FAQs
Evermind - Distributed Lock as a Service
We found that @evermind-sh/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
Socket researchers uncover how threat actors weaponize Discord across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.
Security News
Socket now integrates with Bun 1.3’s Security Scanner API to block risky packages at install time and enforce your organization’s policies in local dev and CI.
Research
The Socket Threat Research Team is tracking weekly intrusions into the npm registry that follow a repeatable adversarial playbook used by North Korean state-sponsored actors.