Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
async-atomic-store
Advanced tools
An agnostic little store abstraction for reading, writing and appending on the same data from multiple sources in a locking manner, that allows concurrent/parallel (like from many async sources) write, append and read
An agnostic little store abstraction for reading, writing and appending on the same data from multiple sources in a locking manner, that allows concurrent/parallel (like from many async sources) write, append and read.
The interface is simple, you provide your read
, write
and data
methods, and it outputs an async-locking write
, read
, append
, lock
and data
methods.
All those methods are async (return a promise), even if they have non-async data underneath, because of the async locking mechanism, which is similar to a LOCK TABLE
and not LOCK ROW
. This does not use loops or saturate the event loop.
If any method throw
, the lock will be released and no changes are made.
const store = AsyncAtomicStore<KEY_OR_ID, TYPE_OR_SHAPE_OF_VALUE, TYPE_OF_STORAGE>({
data: async () => { /* your underlying data */ },
read: async (key) => { /* query a database, read from your datasource */ },
write: async (key, value) => { /* writes in a atomic locking manner */ }
});
// guaranteed to return that point-in-time value
const value = await store.read("id");
// at this exact point, "id" will be "my value"
await store.write("id", "my value");
// passes the current value to the callback, modify it then write at the same key.
// transformedValue = "my value + my value"
const transformedValue = await store.append("id", async (currentValue) => {
return `${currentValue} + ${currentValue}`;
});
// locks everything, passes the current point-in-time datasource, and return an arbitrary value.
// This exists for everything that isn't covered by the other "keyed" methods, but you need to
// do some async work before returning a value
// value = "ok"
const value = await store.lock(async (datasource) => {
datasource[42] = "the answer";
return "ok";
});
Provides the following type-safe adapters for your data:
import { AsyncArray } from 'async-atomic-store'
const myArray = [];
const store = AsyncArray(myArray);
await store.write(0, "ok");
await store.lock(async (arr) => {
arr.push("item"); // there's no other way to manipulate an array other than using lock()
});
myArray[0] === "ok";
myArray[1] === "item";
import { AsyncMap } from 'async-atomic-store'
const myMap = new Map<string, string>();
const store = AsyncMap(myMap);
await store.write("str", "ing");
myMap.get("str") === "ing";
import { AsyncObject } from 'async-atomic-store'
const myObj = Object.create(null);
const store = AsyncObject(myObj);
await store.lock(async (obj) => {
obj.goCrazy = {
with: {
it: true
}
}
});
myObj.goCrazy.with.it === true;
Explicit implementations of different data sources
Using Map
import { AsyncAtomicStore } from 'async-atomic-store'
const lockingMap = () => {
const map = new Map<number, DeepObject>()
return AsyncAtomicStore<number, DeepObject | undefined, typeof map>({
data: async () => map,
read: async (key) => map.get(key),
write: async (key, value) => map.set(key, value!)
})
}
const store = lockingMap()
for (let i = 0; i < 10; i++) {
// don't await
setTimeout(() => {
store.append(1, (value) => {
return {
...value,
deep: {
object: {
1: (value ? value.deep.object[1] : 0) + i
// the first lock will initialize the value to 0
// all subsequent writes will use the current value,
}
}
}
})
}, Math.round(Math.random() * 2))
}
assert(
(await store.data()).get(1)!.deep.object[1] === 45,
'Object value should always be 45'
)
Using Set
:
const setStore = () => {
const set = new Set<string>()
return AsyncAtomicStore<number, string | undefined, string[]>({
read: async (index) => index ? [...set.values()][index] : undefined,
write: async (index, value) => {
const kvs = [...set.values()]
set.clear() // set needs to be recreated each time
kvs[index] = value!
kvs.forEach((v) => set.add(v))
await sleep(2)
},
data: async () => [...set.values()]
})
}
const store = setStore()
await Promise.all([
store.write(0, '0'),
store.write(1, '5'),
store.write(1, '1'),
store.write(2, '7'),
store.write(2, '2'),
store.write(3, '3'),
])
const data = await store.data()
assert(
data.join('') === '0123',
'set should be exactly 0123'
)
Redundantly using Atomics
and SharedArrayBuffer
:
import { AsyncAtomicStore } from 'async-atomic-store'
const uint8Array = () => {
const buffer = new SharedArrayBuffer(16)
const uint8 = new Uint8Array(buffer)
return AsyncAtomicStore<number, number, Uint8Array>({
read: async (index) => Atomics.load(uint8, index),
write: async (index, value) => Atomics.store(uint8, index, value),
data: async () => uint8
})
}
const store = uint8Array()
for (let i = 0; i < 16; i++) {
setTimeout(async () => {
store.append(1, (currentValue) => {
return currentValue + i
})
}, Math.round(Math.random() * 2))
}
store.append(1, (currentValue) => currentValue + 1)
const currentData = await store.data()
assert(
currentData[1] === 121,
'Index 1 should be 121'
)
MIT
FAQs
An agnostic little store abstraction for reading, writing and appending on the same data from multiple sources in a locking manner, that allows concurrent/parallel (like from many async sources) write, append and read
The npm package async-atomic-store receives a total of 4 weekly downloads. As such, async-atomic-store popularity was classified as not popular.
We found that async-atomic-store demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.