@aztec/foundation 0.1.0-alpha10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.cjs +103 -0
- package/.prettierrc.json +6 -0
- package/.tsbuildinfo +1 -0
- package/README.md +1 -0
- package/dest/abi/index.d.ts +137 -0
- package/dest/abi/index.d.ts.map +1 -0
- package/dest/abi/index.js +18 -0
- package/dest/async-map/async_map.test.d.ts +2 -0
- package/dest/async-map/async_map.test.d.ts.map +1 -0
- package/dest/async-map/async_map.test.js +9 -0
- package/dest/async-map/index.d.ts +13 -0
- package/dest/async-map/index.d.ts.map +1 -0
- package/dest/async-map/index.js +19 -0
- package/dest/aztec-address/index.d.ts +96 -0
- package/dest/aztec-address/index.d.ts.map +1 -0
- package/dest/aztec-address/index.js +124 -0
- package/dest/bigint-buffer/bigint-buffer.test.d.ts +2 -0
- package/dest/bigint-buffer/bigint-buffer.test.d.ts.map +1 -0
- package/dest/bigint-buffer/bigint-buffer.test.js +18 -0
- package/dest/bigint-buffer/index.d.ts +35 -0
- package/dest/bigint-buffer/index.d.ts.map +1 -0
- package/dest/bigint-buffer/index.js +68 -0
- package/dest/collection/array.d.ts +30 -0
- package/dest/collection/array.d.ts.map +1 -0
- package/dest/collection/array.js +47 -0
- package/dest/collection/index.d.ts +2 -0
- package/dest/collection/index.d.ts.map +1 -0
- package/dest/collection/index.js +2 -0
- package/dest/crypto/index.d.ts +4 -0
- package/dest/crypto/index.d.ts.map +1 -0
- package/dest/crypto/index.js +4 -0
- package/dest/crypto/keccak/index.d.ts +20 -0
- package/dest/crypto/keccak/index.d.ts.map +1 -0
- package/dest/crypto/keccak/index.js +31 -0
- package/dest/crypto/random/index.d.ts +3 -0
- package/dest/crypto/random/index.d.ts.map +1 -0
- package/dest/crypto/random/index.js +36 -0
- package/dest/crypto/random/index.test.d.ts +2 -0
- package/dest/crypto/random/index.test.d.ts.map +1 -0
- package/dest/crypto/random/index.test.js +13 -0
- package/dest/crypto/sha256/index.d.ts +11 -0
- package/dest/crypto/sha256/index.d.ts.map +1 -0
- package/dest/crypto/sha256/index.js +14 -0
- package/dest/crypto/sha256/index.test.d.ts +2 -0
- package/dest/crypto/sha256/index.test.d.ts.map +1 -0
- package/dest/crypto/sha256/index.test.js +11 -0
- package/dest/errors/index.d.ts +8 -0
- package/dest/errors/index.d.ts.map +1 -0
- package/dest/errors/index.js +8 -0
- package/dest/eth-address/eth_address.test.d.ts +2 -0
- package/dest/eth-address/eth_address.test.d.ts.map +1 -0
- package/dest/eth-address/eth_address.test.js +87 -0
- package/dest/eth-address/index.d.ts +139 -0
- package/dest/eth-address/index.d.ts.map +1 -0
- package/dest/eth-address/index.js +221 -0
- package/dest/fields/coordinate.d.ts +67 -0
- package/dest/fields/coordinate.d.ts.map +1 -0
- package/dest/fields/coordinate.js +95 -0
- package/dest/fields/coordinate.test.d.ts +2 -0
- package/dest/fields/coordinate.test.d.ts.map +1 -0
- package/dest/fields/coordinate.test.js +22 -0
- package/dest/fields/fields.d.ts +170 -0
- package/dest/fields/fields.d.ts.map +1 -0
- package/dest/fields/fields.js +210 -0
- package/dest/fields/index.d.ts +4 -0
- package/dest/fields/index.d.ts.map +1 -0
- package/dest/fields/index.js +4 -0
- package/dest/fields/point.d.ts +111 -0
- package/dest/fields/point.d.ts.map +1 -0
- package/dest/fields/point.js +133 -0
- package/dest/fifo/bounded_serial_queue.d.ts +56 -0
- package/dest/fifo/bounded_serial_queue.d.ts.map +1 -0
- package/dest/fifo/bounded_serial_queue.js +94 -0
- package/dest/fifo/index.d.ts +5 -0
- package/dest/fifo/index.d.ts.map +1 -0
- package/dest/fifo/index.js +5 -0
- package/dest/fifo/memory_fifo.d.ts +55 -0
- package/dest/fifo/memory_fifo.d.ts.map +1 -0
- package/dest/fifo/memory_fifo.js +109 -0
- package/dest/fifo/semaphore.d.ts +23 -0
- package/dest/fifo/semaphore.d.ts.map +1 -0
- package/dest/fifo/semaphore.js +30 -0
- package/dest/fifo/serial_queue.d.ts +48 -0
- package/dest/fifo/serial_queue.d.ts.map +1 -0
- package/dest/fifo/serial_queue.js +74 -0
- package/dest/json-rpc/class_converter.d.ts +109 -0
- package/dest/json-rpc/class_converter.d.ts.map +1 -0
- package/dest/json-rpc/class_converter.js +85 -0
- package/dest/json-rpc/client/index.d.ts +2 -0
- package/dest/json-rpc/client/index.d.ts.map +1 -0
- package/dest/json-rpc/client/index.js +2 -0
- package/dest/json-rpc/client/json_rpc_client.d.ts +22 -0
- package/dest/json-rpc/client/json_rpc_client.d.ts.map +1 -0
- package/dest/json-rpc/client/json_rpc_client.js +83 -0
- package/dest/json-rpc/client/json_rpc_client.test.d.ts +2 -0
- package/dest/json-rpc/client/json_rpc_client.test.d.ts.map +1 -0
- package/dest/json-rpc/client/json_rpc_client.test.js +20 -0
- package/dest/json-rpc/convert.d.ts +22 -0
- package/dest/json-rpc/convert.d.ts.map +1 -0
- package/dest/json-rpc/convert.js +93 -0
- package/dest/json-rpc/convert.test.d.ts +2 -0
- package/dest/json-rpc/convert.test.d.ts.map +1 -0
- package/dest/json-rpc/convert.test.js +14 -0
- package/dest/json-rpc/fixtures/test_state.d.ts +47 -0
- package/dest/json-rpc/fixtures/test_state.d.ts.map +1 -0
- package/dest/json-rpc/fixtures/test_state.js +62 -0
- package/dest/json-rpc/index.d.ts +4 -0
- package/dest/json-rpc/index.d.ts.map +1 -0
- package/dest/json-rpc/index.js +4 -0
- package/dest/json-rpc/js_utils.d.ts +13 -0
- package/dest/json-rpc/js_utils.d.ts.map +1 -0
- package/dest/json-rpc/js_utils.js +18 -0
- package/dest/json-rpc/server/index.d.ts +3 -0
- package/dest/json-rpc/server/index.d.ts.map +1 -0
- package/dest/json-rpc/server/index.js +3 -0
- package/dest/json-rpc/server/json_proxy.d.ts +18 -0
- package/dest/json-rpc/server/json_proxy.d.ts.map +1 -0
- package/dest/json-rpc/server/json_proxy.js +35 -0
- package/dest/json-rpc/server/json_rpc_server.d.ts +34 -0
- package/dest/json-rpc/server/json_rpc_server.d.ts.map +1 -0
- package/dest/json-rpc/server/json_rpc_server.js +109 -0
- package/dest/json-rpc/server/json_rpc_server.test.d.ts +2 -0
- package/dest/json-rpc/server/json_rpc_server.test.d.ts.map +1 -0
- package/dest/json-rpc/server/json_rpc_server.test.js +22 -0
- package/dest/log/console.d.ts +16 -0
- package/dest/log/console.d.ts.map +1 -0
- package/dest/log/console.js +39 -0
- package/dest/log/debug.d.ts +46 -0
- package/dest/log/debug.d.ts.map +1 -0
- package/dest/log/debug.js +75 -0
- package/dest/log/index.d.ts +4 -0
- package/dest/log/index.d.ts.map +1 -0
- package/dest/log/index.js +4 -0
- package/dest/log/log_history.d.ts +31 -0
- package/dest/log/log_history.d.ts.map +1 -0
- package/dest/log/log_history.js +42 -0
- package/dest/log/log_history.test.d.ts +2 -0
- package/dest/log/log_history.test.d.ts.map +1 -0
- package/dest/log/log_history.test.js +78 -0
- package/dest/mutex/index.d.ts +53 -0
- package/dest/mutex/index.d.ts.map +1 -0
- package/dest/mutex/index.js +74 -0
- package/dest/mutex/mutex.test.d.ts +9 -0
- package/dest/mutex/mutex.test.d.ts.map +1 -0
- package/dest/mutex/mutex.test.js +58 -0
- package/dest/mutex/mutex_database.d.ts +10 -0
- package/dest/mutex/mutex_database.d.ts.map +1 -0
- package/dest/mutex/mutex_database.js +2 -0
- package/dest/retry/index.d.ts +33 -0
- package/dest/retry/index.d.ts.map +1 -0
- package/dest/retry/index.js +70 -0
- package/dest/running-promise/index.d.ts +35 -0
- package/dest/running-promise/index.d.ts.map +1 -0
- package/dest/running-promise/index.js +59 -0
- package/dest/serialize/buffer_reader.d.ts +188 -0
- package/dest/serialize/buffer_reader.d.ts.map +1 -0
- package/dest/serialize/buffer_reader.js +229 -0
- package/dest/serialize/buffer_reader.test.d.ts +2 -0
- package/dest/serialize/buffer_reader.test.d.ts.map +1 -0
- package/dest/serialize/buffer_reader.test.js +156 -0
- package/dest/serialize/deserializer.d.ts +134 -0
- package/dest/serialize/deserializer.d.ts.map +1 -0
- package/dest/serialize/deserializer.js +145 -0
- package/dest/serialize/free_funcs.d.ts +203 -0
- package/dest/serialize/free_funcs.d.ts.map +1 -0
- package/dest/serialize/free_funcs.js +250 -0
- package/dest/serialize/index.d.ts +6 -0
- package/dest/serialize/index.d.ts.map +1 -0
- package/dest/serialize/index.js +6 -0
- package/dest/serialize/serialize.test.d.ts +2 -0
- package/dest/serialize/serialize.test.d.ts.map +1 -0
- package/dest/serialize/serialize.test.js +68 -0
- package/dest/serialize/serializer.d.ts +89 -0
- package/dest/serialize/serializer.d.ts.map +1 -0
- package/dest/serialize/serializer.js +111 -0
- package/dest/serialize/types.d.ts +33 -0
- package/dest/serialize/types.d.ts.map +1 -0
- package/dest/serialize/types.js +22 -0
- package/dest/sleep/index.d.ts +52 -0
- package/dest/sleep/index.d.ts.map +1 -0
- package/dest/sleep/index.js +70 -0
- package/dest/timer/index.d.ts +3 -0
- package/dest/timer/index.d.ts.map +1 -0
- package/dest/timer/index.js +3 -0
- package/dest/timer/timeout.d.ts +41 -0
- package/dest/timer/timeout.d.ts.map +1 -0
- package/dest/timer/timeout.js +62 -0
- package/dest/timer/timer.d.ts +33 -0
- package/dest/timer/timer.d.ts.map +1 -0
- package/dest/timer/timer.js +38 -0
- package/dest/transport/browser/index.d.ts +5 -0
- package/dest/transport/browser/index.d.ts.map +1 -0
- package/dest/transport/browser/index.js +5 -0
- package/dest/transport/browser/message_port_socket.d.ts +37 -0
- package/dest/transport/browser/message_port_socket.d.ts.map +1 -0
- package/dest/transport/browser/message_port_socket.js +46 -0
- package/dest/transport/browser/shared_worker_connector.d.ts +19 -0
- package/dest/transport/browser/shared_worker_connector.d.ts.map +1 -0
- package/dest/transport/browser/shared_worker_connector.js +21 -0
- package/dest/transport/browser/shared_worker_listener.d.ts +38 -0
- package/dest/transport/browser/shared_worker_listener.d.ts.map +1 -0
- package/dest/transport/browser/shared_worker_listener.js +37 -0
- package/dest/transport/browser/worker_connector.d.ts +26 -0
- package/dest/transport/browser/worker_connector.d.ts.map +1 -0
- package/dest/transport/browser/worker_connector.js +30 -0
- package/dest/transport/browser/worker_listener.d.ts +39 -0
- package/dest/transport/browser/worker_listener.d.ts.map +1 -0
- package/dest/transport/browser/worker_listener.js +39 -0
- package/dest/transport/dispatch/create_dispatch_fn.d.ts +25 -0
- package/dest/transport/dispatch/create_dispatch_fn.d.ts.map +1 -0
- package/dest/transport/dispatch/create_dispatch_fn.js +18 -0
- package/dest/transport/dispatch/create_dispatch_proxy.d.ts +102 -0
- package/dest/transport/dispatch/create_dispatch_proxy.d.ts.map +1 -0
- package/dest/transport/dispatch/create_dispatch_proxy.js +56 -0
- package/dest/transport/dispatch/messages.d.ts +52 -0
- package/dest/transport/dispatch/messages.d.ts.map +1 -0
- package/dest/transport/dispatch/messages.js +12 -0
- package/dest/transport/index.d.ts +12 -0
- package/dest/transport/index.d.ts.map +1 -0
- package/dest/transport/index.js +12 -0
- package/dest/transport/interface/connector.d.ts +8 -0
- package/dest/transport/interface/connector.d.ts.map +1 -0
- package/dest/transport/interface/connector.js +2 -0
- package/dest/transport/interface/listener.d.ts +13 -0
- package/dest/transport/interface/listener.d.ts.map +1 -0
- package/dest/transport/interface/listener.js +2 -0
- package/dest/transport/interface/socket.d.ts +13 -0
- package/dest/transport/interface/socket.d.ts.map +1 -0
- package/dest/transport/interface/socket.js +2 -0
- package/dest/transport/interface/transferable.d.ts +68 -0
- package/dest/transport/interface/transferable.d.ts.map +1 -0
- package/dest/transport/interface/transferable.js +63 -0
- package/dest/transport/node/index.d.ts +3 -0
- package/dest/transport/node/index.d.ts.map +1 -0
- package/dest/transport/node/index.js +3 -0
- package/dest/transport/node/node_connector.d.ts +28 -0
- package/dest/transport/node/node_connector.d.ts.map +1 -0
- package/dest/transport/node/node_connector.js +28 -0
- package/dest/transport/node/node_connector_socket.d.ts +42 -0
- package/dest/transport/node/node_connector_socket.d.ts.map +1 -0
- package/dest/transport/node/node_connector_socket.js +48 -0
- package/dest/transport/node/node_listener.d.ts +26 -0
- package/dest/transport/node/node_listener.d.ts.map +1 -0
- package/dest/transport/node/node_listener.js +30 -0
- package/dest/transport/node/node_listener_socket.d.ts +37 -0
- package/dest/transport/node/node_listener_socket.d.ts.map +1 -0
- package/dest/transport/node/node_listener_socket.js +44 -0
- package/dest/transport/transport_client.d.ts +61 -0
- package/dest/transport/transport_client.d.ts.map +1 -0
- package/dest/transport/transport_client.js +94 -0
- package/dest/transport/transport_server.d.ts +56 -0
- package/dest/transport/transport_server.d.ts.map +1 -0
- package/dest/transport/transport_server.js +101 -0
- package/dest/types/index.d.ts +7 -0
- package/dest/types/index.d.ts.map +1 -0
- package/dest/types/index.js +2 -0
- package/dest/wasm/index.d.ts +5 -0
- package/dest/wasm/index.d.ts.map +1 -0
- package/dest/wasm/index.js +5 -0
- package/dest/wasm/wasm/empty_wasi_sdk.d.ts +130 -0
- package/dest/wasm/wasm/empty_wasi_sdk.d.ts.map +1 -0
- package/dest/wasm/wasm/empty_wasi_sdk.js +166 -0
- package/dest/wasm/wasm/index.d.ts +2 -0
- package/dest/wasm/wasm/index.d.ts.map +1 -0
- package/dest/wasm/wasm/index.js +2 -0
- package/dest/wasm/wasm/wasm_module.d.ts +135 -0
- package/dest/wasm/wasm/wasm_module.d.ts.map +1 -0
- package/dest/wasm/wasm/wasm_module.js +205 -0
- package/dest/wasm/wasm/wasm_module.test.d.ts +2 -0
- package/dest/wasm/wasm/wasm_module.test.d.ts.map +1 -0
- package/dest/wasm/wasm/wasm_module.test.js +24 -0
- package/dest/wasm/worker/browser/index.d.ts +3 -0
- package/dest/wasm/worker/browser/index.d.ts.map +1 -0
- package/dest/wasm/worker/browser/index.js +3 -0
- package/dest/wasm/worker/browser/start_web_module.d.ts +7 -0
- package/dest/wasm/worker/browser/start_web_module.d.ts.map +1 -0
- package/dest/wasm/worker/browser/start_web_module.js +22 -0
- package/dest/wasm/worker/browser/web_data_store.d.ts +23 -0
- package/dest/wasm/worker/browser/web_data_store.d.ts.map +1 -0
- package/dest/wasm/worker/browser/web_data_store.js +32 -0
- package/dest/wasm/worker/browser/web_worker.d.ts +10 -0
- package/dest/wasm/worker/browser/web_worker.d.ts.map +1 -0
- package/dest/wasm/worker/browser/web_worker.js +23 -0
- package/dest/wasm/worker/data_store.d.ts +9 -0
- package/dest/wasm/worker/data_store.d.ts.map +1 -0
- package/dest/wasm/worker/data_store.js +2 -0
- package/dest/wasm/worker/index.d.ts +3 -0
- package/dest/wasm/worker/index.d.ts.map +1 -0
- package/dest/wasm/worker/index.js +2 -0
- package/dest/wasm/worker/node/index.d.ts +3 -0
- package/dest/wasm/worker/node/index.d.ts.map +1 -0
- package/dest/wasm/worker/node/index.js +3 -0
- package/dest/wasm/worker/node/node_data_store.d.ts +22 -0
- package/dest/wasm/worker/node/node_data_store.d.ts.map +1 -0
- package/dest/wasm/worker/node/node_data_store.js +31 -0
- package/dest/wasm/worker/node/node_worker.d.ts +6 -0
- package/dest/wasm/worker/node/node_worker.d.ts.map +1 -0
- package/dest/wasm/worker/node/node_worker.js +20 -0
- package/dest/wasm/worker/node/start_node_module.d.ts +7 -0
- package/dest/wasm/worker/node/start_node_module.d.ts.map +1 -0
- package/dest/wasm/worker/node/start_node_module.js +26 -0
- package/dest/wasm/worker/wasm_worker.d.ts +9 -0
- package/dest/wasm/worker/wasm_worker.d.ts.map +1 -0
- package/dest/wasm/worker/wasm_worker.js +2 -0
- package/dest/wasm/worker/worker_pool.d.ts +40 -0
- package/dest/wasm/worker/worker_pool.d.ts.map +1 -0
- package/dest/wasm/worker/worker_pool.js +62 -0
- package/package.json +44 -0
- package/src/abi/index.ts +147 -0
- package/src/async-map/async_map.test.ts +9 -0
- package/src/async-map/index.ts +18 -0
- package/src/aztec-address/index.ts +135 -0
- package/src/bigint-buffer/bigint-buffer.test.ts +21 -0
- package/src/bigint-buffer/index.ts +68 -0
- package/src/collection/array.ts +48 -0
- package/src/collection/index.ts +1 -0
- package/src/crypto/index.ts +3 -0
- package/src/crypto/keccak/index.ts +33 -0
- package/src/crypto/random/index.test.ts +13 -0
- package/src/crypto/random/index.ts +38 -0
- package/src/crypto/sha256/index.test.ts +13 -0
- package/src/crypto/sha256/index.ts +15 -0
- package/src/errors/index.ts +6 -0
- package/src/eth-address/eth_address.test.ts +104 -0
- package/src/eth-address/index.ts +236 -0
- package/src/fields/coordinate.test.ts +26 -0
- package/src/fields/coordinate.ts +104 -0
- package/src/fields/fields.ts +234 -0
- package/src/fields/index.ts +3 -0
- package/src/fields/point.ts +143 -0
- package/src/fifo/bounded_serial_queue.ts +100 -0
- package/src/fifo/index.ts +4 -0
- package/src/fifo/memory_fifo.ts +114 -0
- package/src/fifo/semaphore.ts +33 -0
- package/src/fifo/serial_queue.ts +78 -0
- package/src/json-rpc/README.md +55 -0
- package/src/json-rpc/class_converter.ts +160 -0
- package/src/json-rpc/client/index.ts +1 -0
- package/src/json-rpc/client/json_rpc_client.test.ts +20 -0
- package/src/json-rpc/client/json_rpc_client.ts +103 -0
- package/src/json-rpc/convert.test.ts +15 -0
- package/src/json-rpc/convert.ts +109 -0
- package/src/json-rpc/fixtures/test_state.ts +59 -0
- package/src/json-rpc/index.ts +3 -0
- package/src/json-rpc/js_utils.ts +20 -0
- package/src/json-rpc/server/index.ts +2 -0
- package/src/json-rpc/server/json_proxy.ts +36 -0
- package/src/json-rpc/server/json_rpc_server.test.ts +23 -0
- package/src/json-rpc/server/json_rpc_server.ts +124 -0
- package/src/log/console.ts +45 -0
- package/src/log/debug.ts +86 -0
- package/src/log/index.ts +3 -0
- package/src/log/log_history.test.ts +87 -0
- package/src/log/log_history.ts +44 -0
- package/src/mutex/index.ts +83 -0
- package/src/mutex/mutex.test.ts +75 -0
- package/src/mutex/mutex_database.ts +9 -0
- package/src/retry/index.ts +78 -0
- package/src/running-promise/index.ts +60 -0
- package/src/serialize/buffer_reader.test.ts +175 -0
- package/src/serialize/buffer_reader.ts +272 -0
- package/src/serialize/deserializer.ts +180 -0
- package/src/serialize/free_funcs.ts +285 -0
- package/src/serialize/index.ts +5 -0
- package/src/serialize/serialize.test.ts +89 -0
- package/src/serialize/serializer.ts +128 -0
- package/src/serialize/types.ts +40 -0
- package/src/sleep/index.ts +71 -0
- package/src/timer/index.ts +2 -0
- package/src/timer/timeout.ts +64 -0
- package/src/timer/timer.ts +41 -0
- package/src/transport/browser/index.ts +4 -0
- package/src/transport/browser/message_port_socket.ts +48 -0
- package/src/transport/browser/shared_worker_connector.ts +21 -0
- package/src/transport/browser/shared_worker_listener.ts +52 -0
- package/src/transport/browser/worker_connector.ts +30 -0
- package/src/transport/browser/worker_listener.ts +53 -0
- package/src/transport/dispatch/create_dispatch_fn.ts +33 -0
- package/src/transport/dispatch/create_dispatch_proxy.ts +140 -0
- package/src/transport/dispatch/messages.ts +58 -0
- package/src/transport/index.ts +11 -0
- package/src/transport/interface/connector.ts +8 -0
- package/src/transport/interface/listener.ts +14 -0
- package/src/transport/interface/socket.ts +12 -0
- package/src/transport/interface/transferable.ts +121 -0
- package/src/transport/node/index.ts +2 -0
- package/src/transport/node/node_connector.ts +29 -0
- package/src/transport/node/node_connector_socket.ts +51 -0
- package/src/transport/node/node_listener.ts +33 -0
- package/src/transport/node/node_listener_socket.ts +47 -0
- package/src/transport/transport_client.ts +125 -0
- package/src/transport/transport_server.ts +108 -0
- package/src/types/index.ts +7 -0
- package/src/wasm/README.md +6 -0
- package/src/wasm/fixtures/gcd.wasm +0 -0
- package/src/wasm/fixtures/gcd.wat +27 -0
- package/src/wasm/index.ts +4 -0
- package/src/wasm/wasm/empty_wasi_sdk.ts +166 -0
- package/src/wasm/wasm/index.ts +1 -0
- package/src/wasm/wasm/wasm_module.test.ts +27 -0
- package/src/wasm/wasm/wasm_module.ts +257 -0
- package/src/wasm/worker/browser/index.ts +2 -0
- package/src/wasm/worker/browser/start_web_module.ts +23 -0
- package/src/wasm/worker/browser/web_data_store.ts +37 -0
- package/src/wasm/worker/browser/web_worker.ts +24 -0
- package/src/wasm/worker/data_store.ts +7 -0
- package/src/wasm/worker/index.ts +2 -0
- package/src/wasm/worker/node/index.ts +2 -0
- package/src/wasm/worker/node/node_data_store.ts +36 -0
- package/src/wasm/worker/node/node_worker.ts +21 -0
- package/src/wasm/worker/node/start_node_module.ts +28 -0
- package/src/wasm/worker/wasm_worker.ts +7 -0
- package/src/wasm/worker/worker_pool.ts +73 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import request from 'supertest';
|
|
2
|
+
import { TestState, TestNote } from '../fixtures/test_state.js';
|
|
3
|
+
import { JsonRpcServer } from './json_rpc_server.js';
|
|
4
|
+
|
|
5
|
+
test('test an RPC function with a primitive parameter', async () => {
|
|
6
|
+
const server = new JsonRpcServer(new TestState([new TestNote('a'), new TestNote('b')]), { TestNote }, {}, true);
|
|
7
|
+
const response = await request(server.getApp().callback())
|
|
8
|
+
.post('/getNote')
|
|
9
|
+
.send({ params: [0] });
|
|
10
|
+
expect(response.status).toBe(200);
|
|
11
|
+
expect(response.text).toBe(JSON.stringify({ result: JSON.stringify({ type: 'TestNote', data: 'a' }) }));
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('test an RPC function with an array of classes', async () => {
|
|
15
|
+
const server = new JsonRpcServer(new TestState([]), { TestNote }, {}, true);
|
|
16
|
+
const response = await request(server.getApp().callback())
|
|
17
|
+
.post('/addNotes')
|
|
18
|
+
.send({
|
|
19
|
+
params: [[{ data: 'a' }, { data: 'b' }, { data: 'c' }]],
|
|
20
|
+
});
|
|
21
|
+
expect(response.status).toBe(200);
|
|
22
|
+
expect(response.text).toBe(JSON.stringify({ result: JSON.stringify([{ data: 'a' }, { data: 'b' }, { data: 'c' }]) }));
|
|
23
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import Router from 'koa-router';
|
|
3
|
+
import cors from '@koa/cors';
|
|
4
|
+
import compress from 'koa-compress';
|
|
5
|
+
import Koa from 'koa';
|
|
6
|
+
import bodyParser from 'koa-bodyparser';
|
|
7
|
+
|
|
8
|
+
import { createLogger } from '../../log/index.js';
|
|
9
|
+
import { ClassConverterInput } from '../class_converter.js';
|
|
10
|
+
import { JsonProxy } from './json_proxy.js';
|
|
11
|
+
import { JsonStringify } from '../convert.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* JsonRpcServer.
|
|
15
|
+
* Minimal, dev-friendly mechanism to create a server from an object.
|
|
16
|
+
*/
|
|
17
|
+
export class JsonRpcServer {
|
|
18
|
+
proxy: JsonProxy;
|
|
19
|
+
constructor(
|
|
20
|
+
private handler: object,
|
|
21
|
+
stringClassMap: ClassConverterInput,
|
|
22
|
+
objectClassMap: ClassConverterInput,
|
|
23
|
+
private createApi: boolean,
|
|
24
|
+
private disallowedMethods: string[] = [],
|
|
25
|
+
private log = createLogger('aztec:foundation:json-rpc:server'),
|
|
26
|
+
) {
|
|
27
|
+
this.proxy = new JsonProxy(handler, stringClassMap, objectClassMap);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get an express app object.
|
|
32
|
+
* @param prefix - Our server prefix.
|
|
33
|
+
* @returns The app object.
|
|
34
|
+
*/
|
|
35
|
+
public getApp(prefix = '') {
|
|
36
|
+
const router = this.getRouter(prefix);
|
|
37
|
+
const exceptionHandler = async (ctx: Koa.Context, next: () => Promise<void>) => {
|
|
38
|
+
try {
|
|
39
|
+
await next();
|
|
40
|
+
} catch (err: any) {
|
|
41
|
+
this.log(err);
|
|
42
|
+
ctx.status = 400;
|
|
43
|
+
ctx.body = { error: err.message };
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const app = new Koa();
|
|
47
|
+
app.on('error', error => {
|
|
48
|
+
this.log(`KOA app-level error. ${JsonStringify({ error })}`);
|
|
49
|
+
});
|
|
50
|
+
app.use(compress({ br: false } as any));
|
|
51
|
+
app.use(bodyParser());
|
|
52
|
+
app.use(cors());
|
|
53
|
+
app.use(exceptionHandler);
|
|
54
|
+
app.use(router.routes());
|
|
55
|
+
app.use(router.allowedMethods());
|
|
56
|
+
|
|
57
|
+
return app;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get a router object wrapping our RPC class.
|
|
62
|
+
* @param prefix - The server prefix.
|
|
63
|
+
* @returns The router object.
|
|
64
|
+
*/
|
|
65
|
+
private getRouter(prefix: string) {
|
|
66
|
+
const router = new Router({ prefix });
|
|
67
|
+
const proto = Object.getPrototypeOf(this.handler);
|
|
68
|
+
// Find all our endpoints from the handler methods
|
|
69
|
+
|
|
70
|
+
if (this.createApi) {
|
|
71
|
+
// "API mode" where an endpoint is created for each method
|
|
72
|
+
for (const method of Object.getOwnPropertyNames(proto)) {
|
|
73
|
+
// Ignore if not a function or function is not allowed
|
|
74
|
+
if (
|
|
75
|
+
method === 'constructor' ||
|
|
76
|
+
typeof proto[method] !== 'function' ||
|
|
77
|
+
this.disallowedMethods.includes(method)
|
|
78
|
+
) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
router.post(`/${method}`, async (ctx: Koa.Context) => {
|
|
82
|
+
const { params = [], jsonrpc, id } = ctx.request.body as any;
|
|
83
|
+
const result = await this.proxy.call(method, params);
|
|
84
|
+
ctx.body = { jsonrpc, id, result: JsonStringify(result) };
|
|
85
|
+
ctx.status = 200;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
// "JSON RPC mode" where a single endpoint is used and the method is given in the request body
|
|
90
|
+
router.post('/', async (ctx: Koa.Context) => {
|
|
91
|
+
const { params = [], jsonrpc, id, method } = ctx.request.body as any;
|
|
92
|
+
// Ignore if not a function
|
|
93
|
+
if (
|
|
94
|
+
method === 'constructor' ||
|
|
95
|
+
typeof proto[method] !== 'function' ||
|
|
96
|
+
this.disallowedMethods.includes(method)
|
|
97
|
+
) {
|
|
98
|
+
ctx.status = 400;
|
|
99
|
+
ctx.body = { error: `Invalid method name: ${method}` };
|
|
100
|
+
}
|
|
101
|
+
const result = await this.proxy.call(method, params);
|
|
102
|
+
|
|
103
|
+
ctx.body = {
|
|
104
|
+
jsonrpc,
|
|
105
|
+
id,
|
|
106
|
+
result: JsonStringify(result),
|
|
107
|
+
};
|
|
108
|
+
ctx.status = 200;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return router;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Start this server with koa.
|
|
117
|
+
* @param port - Port number.
|
|
118
|
+
* @param prefix - Prefix string.
|
|
119
|
+
*/
|
|
120
|
+
public start(port: number, prefix = '') {
|
|
121
|
+
const httpServer = http.createServer(this.getApp(prefix).callback());
|
|
122
|
+
httpServer.listen(port);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Logger is a utility type that represents a logging function that accepts any number of arguments.
|
|
5
|
+
* It is used to provide customizable logging functionality, allowing developers to easily log messages
|
|
6
|
+
* with optional prefixes and custom formatting or output destinations.
|
|
7
|
+
*/
|
|
8
|
+
export type Logger = (...args: any[]) => void;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* ConsoleLogger is a utility class that provides customizable console logging functionality.
|
|
12
|
+
* It allows setting a custom prefix for log messages and an optional custom logger function,
|
|
13
|
+
* which can be useful for controlling the format of the output or redirecting logs to a different destination.
|
|
14
|
+
*/
|
|
15
|
+
class ConsoleLogger {
|
|
16
|
+
constructor(private prefix: string, private logger: (...args: any[]) => void = console.log) {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Log messages with the specified prefix using the provided logger.
|
|
20
|
+
* By default, it uses 'console.log' as the logger but can be overridden
|
|
21
|
+
* during ConsoleLogger instantiation. This method allows for easy
|
|
22
|
+
* organization and readability of log messages in the console.
|
|
23
|
+
*
|
|
24
|
+
* @param args - The data to be logged, any number of arguments can be passed to this function.
|
|
25
|
+
*/
|
|
26
|
+
public log(...args: any[]) {
|
|
27
|
+
this.logger(`${this.prefix}:`, ...args);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a Logger function with an optional prefix for log messages.
|
|
33
|
+
* If a prefix is provided, the created logger will prepend it to each log message.
|
|
34
|
+
* If no prefix is provided, the default console.log will be returned.
|
|
35
|
+
*
|
|
36
|
+
* @param prefix - The optional string to prepend to each log message.
|
|
37
|
+
* @returns A Logger function that accepts any number of arguments and logs them with the specified prefix.
|
|
38
|
+
*/
|
|
39
|
+
export function createLogger(prefix?: string): Logger {
|
|
40
|
+
if (prefix) {
|
|
41
|
+
const logger = new ConsoleLogger(prefix, console.log);
|
|
42
|
+
return (...args: any[]) => logger.log(...args);
|
|
43
|
+
}
|
|
44
|
+
return console.log;
|
|
45
|
+
}
|
package/src/log/debug.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import debug from 'debug';
|
|
2
|
+
|
|
3
|
+
let preLogHook: ((...args: any[]) => void) | undefined;
|
|
4
|
+
let postLogHook: ((...args: any[]) => void) | undefined;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Process and handle the logging of messages through custom hooks and the given logger.
|
|
8
|
+
* This function checks if the logger's namespace is enabled, executes any preLogHook functions, logs the message using the provided logger, and then executes any postLogHook functions.
|
|
9
|
+
*
|
|
10
|
+
* @param logger - The debug logger instance to be used for logging.
|
|
11
|
+
* @param args - The arguments to be passed to the logger and any hook functions.
|
|
12
|
+
*/
|
|
13
|
+
function theFunctionThroughWhichAllLogsPass(logger: any, ...args: any[]) {
|
|
14
|
+
if (!debug.enabled(logger.namespace)) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (preLogHook) {
|
|
18
|
+
preLogHook(logger.namespace, ...args);
|
|
19
|
+
}
|
|
20
|
+
logger(...args);
|
|
21
|
+
if (postLogHook) {
|
|
22
|
+
postLogHook(logger.namespace, ...args);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A debug logger.
|
|
28
|
+
*/
|
|
29
|
+
export type DebugLogger = (...args: any[]) => void;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Return a logger, meant to be silent by default and verbose during debugging.
|
|
33
|
+
* @param name - The module name of the logger.
|
|
34
|
+
* @returns A callable log function.
|
|
35
|
+
*/
|
|
36
|
+
export function createDebugLogger(name: string): DebugLogger {
|
|
37
|
+
const logger = debug(name);
|
|
38
|
+
return (...args: any[]) => theFunctionThroughWhichAllLogsPass(logger, ...args);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Set a function to be called before each log message is handled by the debug logger.
|
|
43
|
+
* The hook function will receive the logger namespace and any arguments passed to the logger.
|
|
44
|
+
* This can be useful for adding additional context, filtering logs, or performing side-effects
|
|
45
|
+
* based on logged messages.
|
|
46
|
+
*
|
|
47
|
+
* @param fn - The function to be called before each log message.
|
|
48
|
+
*/
|
|
49
|
+
export function setPreDebugLogHook(fn: (...args: any[]) => void) {
|
|
50
|
+
preLogHook = fn;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Set a callback function to be executed after each log is written by the debug logger.
|
|
55
|
+
* This allows additional behavior or side effects to occur after a log has been written,
|
|
56
|
+
* such as sending logs to external services, formatting output, or triggering events.
|
|
57
|
+
*
|
|
58
|
+
* @param fn - The callback function to be executed after each log. It receives the same arguments as the original log function call.
|
|
59
|
+
*/
|
|
60
|
+
export function setPostDebugLogHook(fn: (...args: any[]) => void) {
|
|
61
|
+
postLogHook = fn;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Enable logs for the specified namespace(s) or wildcard pattern(s).
|
|
66
|
+
* This function activates the logging functionality for the given
|
|
67
|
+
* namespace(s) or pattern(s), allowing developers to selectively display
|
|
68
|
+
* debug logs that match the provided string(s).
|
|
69
|
+
*
|
|
70
|
+
* @param str - The namespace(s) or wildcard pattern(s) for which logs should be enabled.
|
|
71
|
+
*/
|
|
72
|
+
export function enableLogs(str: string) {
|
|
73
|
+
debug.enable(str);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if the logging is enabled for a given namespace.
|
|
78
|
+
* The input 'str' represents the namespace for which the log status is being checked.
|
|
79
|
+
* Returns true if the logging is enabled, otherwise false.
|
|
80
|
+
*
|
|
81
|
+
* @param str - The namespace string used to determine if logging is enabled.
|
|
82
|
+
* @returns A boolean indicating whether logging is enabled for the given namespace.
|
|
83
|
+
*/
|
|
84
|
+
export function isLogEnabled(str: string) {
|
|
85
|
+
return debug.enabled(str);
|
|
86
|
+
}
|
package/src/log/index.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { createDebugLogger, enableLogs } from './debug.js';
|
|
3
|
+
import { LogHistory } from './log_history.js';
|
|
4
|
+
|
|
5
|
+
jest.useFakeTimers({ doNotFake: ['performance'] });
|
|
6
|
+
|
|
7
|
+
describe('log history', () => {
|
|
8
|
+
let debug: (...any: any) => void;
|
|
9
|
+
let logHistory: LogHistory;
|
|
10
|
+
const timestemp = new Date().toISOString();
|
|
11
|
+
const name = 'test:a';
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
debug = createDebugLogger(name);
|
|
15
|
+
enableLogs(name);
|
|
16
|
+
logHistory = new LogHistory();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('keeps debug logs', () => {
|
|
20
|
+
logHistory.enable();
|
|
21
|
+
expect(logHistory.getLogs()).toEqual([]);
|
|
22
|
+
debug('0');
|
|
23
|
+
debug('1', 2);
|
|
24
|
+
debug('2', { key: ['value'] }, Buffer.alloc(2));
|
|
25
|
+
expect(logHistory.getLogs()).toEqual([
|
|
26
|
+
[timestemp, name, '0'],
|
|
27
|
+
[timestemp, name, '1', 2],
|
|
28
|
+
[timestemp, name, '2', { key: ['value'] }, Buffer.alloc(2)],
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('does not keep logs if not enabled', () => {
|
|
33
|
+
debug('0');
|
|
34
|
+
debug('1', 2);
|
|
35
|
+
expect(logHistory.getLogs()).toEqual([]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('returns last n logs', () => {
|
|
39
|
+
logHistory.enable();
|
|
40
|
+
expect(logHistory.getLogs()).toEqual([]);
|
|
41
|
+
debug('0');
|
|
42
|
+
debug('1');
|
|
43
|
+
debug('2');
|
|
44
|
+
debug('3');
|
|
45
|
+
debug('4');
|
|
46
|
+
expect(logHistory.getLogs(2)).toEqual([
|
|
47
|
+
[timestemp, name, '3'],
|
|
48
|
+
[timestemp, name, '4'],
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('only keeps logs with enabled namespace', () => {
|
|
53
|
+
logHistory.enable();
|
|
54
|
+
const name2 = 'test:b';
|
|
55
|
+
const debug2 = createDebugLogger(name2);
|
|
56
|
+
debug('0');
|
|
57
|
+
debug2('zero');
|
|
58
|
+
expect(logHistory.getLogs()).toEqual([[timestemp, name, '0']]);
|
|
59
|
+
|
|
60
|
+
enableLogs(`${name},${name2}`);
|
|
61
|
+
debug('1', 2);
|
|
62
|
+
debug2('one', 3);
|
|
63
|
+
expect(logHistory.getLogs()).toEqual([
|
|
64
|
+
[timestemp, name, '0'],
|
|
65
|
+
[timestemp, name, '1', 2],
|
|
66
|
+
[timestemp, name2, 'one', 3],
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('clears all logs', () => {
|
|
71
|
+
logHistory.enable();
|
|
72
|
+
debug('0');
|
|
73
|
+
debug('1');
|
|
74
|
+
debug('2');
|
|
75
|
+
logHistory.clear();
|
|
76
|
+
expect(logHistory.getLogs()).toEqual([]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('clears first n logs', () => {
|
|
80
|
+
logHistory.enable();
|
|
81
|
+
debug('0');
|
|
82
|
+
debug('1');
|
|
83
|
+
debug('2');
|
|
84
|
+
logHistory.clear(2);
|
|
85
|
+
expect(logHistory.getLogs()).toEqual([[timestemp, name, '2']]);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { setPreDebugLogHook } from './debug.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* LogHistory is a utility class that provides the ability to store and manage debug logs.
|
|
5
|
+
* It can be enabled to record logs along with their timestamps, retrieve a specified number
|
|
6
|
+
* of recent logs, or clear stored logs based on a given count. This can be useful for debugging
|
|
7
|
+
* purposes, monitoring application activities, and maintaining log history.
|
|
8
|
+
*/
|
|
9
|
+
export class LogHistory {
|
|
10
|
+
private logs: any[][] = [];
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Enables the logging of debug messages with timestamps.
|
|
14
|
+
* Hooks into the pre-debug log and stores each log entry along with its timestamp in the logs array.
|
|
15
|
+
*/
|
|
16
|
+
public enable() {
|
|
17
|
+
setPreDebugLogHook((...args: any[]) => {
|
|
18
|
+
this.logs.push([new Date().toISOString(), ...args]);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Retrieves a specified number of logs from the end of the log history or all logs if no argument is provided.
|
|
24
|
+
* The logs are ordered chronologically, with the oldest logs at the beginning of the array.
|
|
25
|
+
*
|
|
26
|
+
* @param last - Optional number representing the amount of recent logs to return. Defaults to 0, which returns all logs.
|
|
27
|
+
* @returns An array of log arrays, each containing a timestamp and log arguments.
|
|
28
|
+
*/
|
|
29
|
+
public getLogs(last = 0) {
|
|
30
|
+
return last ? this.logs.slice(-last) : this.logs;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Clear a specified number of logs from the beginning of the logs array.
|
|
35
|
+
* If no count is provided, it will clear all logs.
|
|
36
|
+
*
|
|
37
|
+
* @param count - The number of logs to be removed (default: total logs length).
|
|
38
|
+
*/
|
|
39
|
+
public clear(count = this.logs.length) {
|
|
40
|
+
this.logs = this.logs.slice(count);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const logHistory = new LogHistory();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { MutexDatabase } from './mutex_database.js';
|
|
2
|
+
|
|
3
|
+
export * from './mutex_database.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Mutex class provides a mutual exclusion mechanism for critical sections of code using a named lock.
|
|
7
|
+
* The lock is acquired and released via the `lock` and `unlock` methods. Locks can be optionally pinged
|
|
8
|
+
* to keep them alive when they are held for longer durations, avoiding unintended release due to timeouts.
|
|
9
|
+
*
|
|
10
|
+
* The underlying lock state is managed in a MutexDatabase instance which can be shared across multiple Mutex instances.
|
|
11
|
+
* This allows for synchronization between different parts of an application or even across different instances of an application.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const mutex = new Mutex(mutexDatabase, 'myLock');
|
|
15
|
+
* await mutex.lock();
|
|
16
|
+
* // Critical section here
|
|
17
|
+
* await mutex.unlock();
|
|
18
|
+
*/
|
|
19
|
+
export class Mutex {
|
|
20
|
+
private id = 0;
|
|
21
|
+
private pingTimeout!: NodeJS.Timeout;
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
private readonly db: MutexDatabase,
|
|
25
|
+
private readonly name: string,
|
|
26
|
+
private readonly timeout = 5000,
|
|
27
|
+
private readonly tryLockInterval = 2000,
|
|
28
|
+
private readonly pingInterval = 2000,
|
|
29
|
+
) {}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Acquire a lock on the mutex. If 'untilAcquired' is true, the method will keep trying to acquire the lock until it
|
|
33
|
+
* successfully acquires it. If 'untilAcquired' is false, the method will try to acquire the lock once and return
|
|
34
|
+
* immediately with a boolean indicating if the lock has been acquired or not.
|
|
35
|
+
*
|
|
36
|
+
* @param untilAcquired - Optional parameter, set to true by default. If true, the method will keep trying to acquire the lock until success. If false, the method will try only once and return a boolean value.
|
|
37
|
+
* @returns A Promise that resolves to true if the lock has been acquired, or false when 'untilAcquired' is false and the lock could not be immediately acquired.
|
|
38
|
+
*/
|
|
39
|
+
public async lock(untilAcquired = true) {
|
|
40
|
+
while (true) {
|
|
41
|
+
if (await this.db.acquireLock(this.name, this.timeout)) {
|
|
42
|
+
const id = this.id;
|
|
43
|
+
this.pingTimeout = setTimeout(() => this.ping(id), this.pingInterval);
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!untilAcquired) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
await new Promise(resolve => setTimeout(resolve, this.tryLockInterval));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Unlocks the mutex, allowing other instances to acquire the lock.
|
|
56
|
+
* This method also clears the internal ping timeout and increments the internal ID
|
|
57
|
+
* to ensure stale pings do not extend the lock after it has been released.
|
|
58
|
+
*
|
|
59
|
+
* @returns A promise that resolves once the lock has been released in the database.
|
|
60
|
+
*/
|
|
61
|
+
public async unlock() {
|
|
62
|
+
clearTimeout(this.pingTimeout);
|
|
63
|
+
this.id++;
|
|
64
|
+
await this.db.releaseLock(this.name);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Periodically extends the lock's lifetime by updating the database record with a new expiration time.
|
|
69
|
+
* This method is called recursively using setTimeout. If the id passed to the ping method does not match
|
|
70
|
+
* the current lock instance's id, it means the lock has been released or acquired by another instance
|
|
71
|
+
* and the ping should not proceed further.
|
|
72
|
+
*
|
|
73
|
+
* @param id - The id of the current lock instance.
|
|
74
|
+
*/
|
|
75
|
+
private async ping(id: number) {
|
|
76
|
+
if (id !== this.id) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
await this.db.extendLock(this.name, this.timeout);
|
|
81
|
+
this.pingTimeout = setTimeout(() => this.ping(id), this.pingInterval);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { Mutex } from './index.js';
|
|
3
|
+
import { MutexDatabase } from './mutex_database.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Sleep function for introducing a delay in the execution of code.
|
|
7
|
+
* Returns a Promise that resolves after the specified number of milliseconds.
|
|
8
|
+
*
|
|
9
|
+
* @param ms - The number of milliseconds to pause the execution.
|
|
10
|
+
* @returns A Promise that resolves after the specified delay.
|
|
11
|
+
*/
|
|
12
|
+
export function sleep(ms: number) {
|
|
13
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Type that transforms the properties of an object into jest.Mock instances,
|
|
18
|
+
* allowing for easy mocking and testing of functions and methods.
|
|
19
|
+
*/
|
|
20
|
+
type Mockify<T> = {
|
|
21
|
+
[P in keyof T]: jest.Mock;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
describe('mutex', () => {
|
|
25
|
+
let db: Mockify<MutexDatabase>;
|
|
26
|
+
let mutex: Mutex;
|
|
27
|
+
const mutexName = 'test-mutex';
|
|
28
|
+
const timeout = 500;
|
|
29
|
+
const tryLockInterval = 100;
|
|
30
|
+
const pingInterval = 200;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
db = {
|
|
34
|
+
acquireLock: jest.fn().mockImplementation(() => false),
|
|
35
|
+
extendLock: jest.fn().mockImplementation(() => {
|
|
36
|
+
(db.acquireLock.mockResolvedValueOnce as any)(false);
|
|
37
|
+
}),
|
|
38
|
+
releaseLock: jest.fn().mockImplementation(() => {
|
|
39
|
+
(db.acquireLock.mockResolvedValueOnce as any)(true);
|
|
40
|
+
}),
|
|
41
|
+
} as any;
|
|
42
|
+
(db.acquireLock.mockResolvedValueOnce as any)(true);
|
|
43
|
+
|
|
44
|
+
mutex = new Mutex(db as MutexDatabase, mutexName, timeout, tryLockInterval, pingInterval);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('cannot lock if locked', async () => {
|
|
48
|
+
const result: string[] = [];
|
|
49
|
+
const fn1 = async (runAfterLocked: () => Promise<void>) => {
|
|
50
|
+
await mutex.lock();
|
|
51
|
+
const pm = runAfterLocked();
|
|
52
|
+
await sleep(500);
|
|
53
|
+
result.push('fn1');
|
|
54
|
+
await mutex.unlock();
|
|
55
|
+
return pm;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const fn2 = async () => {
|
|
59
|
+
await mutex.lock();
|
|
60
|
+
result.push('fn2');
|
|
61
|
+
await mutex.unlock();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
await fn1(fn2);
|
|
65
|
+
expect(result).toEqual(['fn1', 'fn2']);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('automatically extend the expiry time of the lock', async () => {
|
|
69
|
+
await mutex.lock();
|
|
70
|
+
await sleep(1000);
|
|
71
|
+
await mutex.unlock();
|
|
72
|
+
|
|
73
|
+
expect(db.extendLock).toHaveBeenCalledWith(mutexName, timeout);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a mutual exclusion (mutex) database interface.
|
|
3
|
+
* Provides functionality for acquiring, extending, and releasing locks on resources to ensure exclusive access and prevent conflicts in concurrent applications.
|
|
4
|
+
*/
|
|
5
|
+
export interface MutexDatabase {
|
|
6
|
+
acquireLock(name: string, timeout: number): Promise<boolean>;
|
|
7
|
+
extendLock(name: string, timeout: number): Promise<void>;
|
|
8
|
+
releaseLock(name: string): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { createLogger } from '../log/index.js';
|
|
2
|
+
import { sleep } from '../sleep/index.js';
|
|
3
|
+
import { Timer } from '../timer/index.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generates a backoff sequence for retrying operations with an increasing delay.
|
|
7
|
+
* The backoff sequence follows this pattern: 1, 1, 1, 2, 4, 8, 16, 32, 64, ...
|
|
8
|
+
* This generator can be used in combination with the `retry` function to perform
|
|
9
|
+
* retries with exponential backoff and capped at 64 seconds between attempts.
|
|
10
|
+
*
|
|
11
|
+
* @returns A generator that yields the next backoff value in seconds as an integer.
|
|
12
|
+
*/
|
|
13
|
+
export function* backoffGenerator() {
|
|
14
|
+
const v = [1, 1, 1, 2, 4, 8, 16, 32, 64];
|
|
15
|
+
let i = 0;
|
|
16
|
+
while (true) {
|
|
17
|
+
yield v[Math.min(i++, v.length - 1)];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Retry a given asynchronous function with a specific backoff strategy, until it succeeds or backoff generator ends.
|
|
23
|
+
* It logs the error and retry interval in case an error is caught. The function can be named for better log output.
|
|
24
|
+
*
|
|
25
|
+
* @param fn - The asynchronous function to be retried.
|
|
26
|
+
* @param name - The optional name of the operation, used for logging purposes.
|
|
27
|
+
* @param backoff - The optional backoff generator providing the intervals in seconds between retries. Defaults to a predefined series.
|
|
28
|
+
* @param log - Logger to use for logging.
|
|
29
|
+
* @returns A Promise that resolves with the successful result of the provided function, or rejects if backoff generator ends.
|
|
30
|
+
*/
|
|
31
|
+
export async function retry<Result>(
|
|
32
|
+
fn: () => Promise<Result>,
|
|
33
|
+
name = 'Operation',
|
|
34
|
+
backoff = backoffGenerator(),
|
|
35
|
+
log = createLogger('aztec:foundation:retry'),
|
|
36
|
+
) {
|
|
37
|
+
while (true) {
|
|
38
|
+
try {
|
|
39
|
+
return await fn();
|
|
40
|
+
} catch (err: any) {
|
|
41
|
+
const s = backoff.next().value;
|
|
42
|
+
if (s === undefined) {
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
log(`${name} failed. Will retry in ${s}s...`);
|
|
46
|
+
log(err);
|
|
47
|
+
await sleep(s * 1000);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Retry an asynchronous function until it returns a truthy value or the specified timeout is exceeded.
|
|
55
|
+
* The function is retried periodically with a fixed interval between attempts. The operation can be named for better error messages.
|
|
56
|
+
* Will never timeout if the value is 0.
|
|
57
|
+
*
|
|
58
|
+
* @param fn - The asynchronous function to be retried, which should return a truthy value upon success or undefined otherwise.
|
|
59
|
+
* @param name - The optional name of the operation, used for generating timeout error message.
|
|
60
|
+
* @param timeout - The optional maximum time, in seconds, to keep retrying before throwing a timeout error. Defaults to 0 (never timeout).
|
|
61
|
+
* @param interval - The optional interval, in seconds, between retry attempts. Defaults to 1 second.
|
|
62
|
+
* @returns A Promise that resolves with the successful (truthy) result of the provided function, or rejects if timeout is exceeded.
|
|
63
|
+
*/
|
|
64
|
+
export async function retryUntil<T>(fn: () => Promise<T | undefined>, name = '', timeout = 0, interval = 1) {
|
|
65
|
+
const timer = new Timer();
|
|
66
|
+
while (true) {
|
|
67
|
+
const result = await fn();
|
|
68
|
+
if (result) {
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
await sleep(interval * 1000);
|
|
73
|
+
|
|
74
|
+
if (timeout && timer.s() > timeout) {
|
|
75
|
+
throw new Error(name ? `Timeout awaiting ${name}` : 'Timeout');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|