├── crates ├── grpc │ ├── proto │ ├── src │ │ └── grpc_gen.rs │ ├── build.rs │ └── Cargo.toml ├── utils │ ├── wit │ ├── src │ │ ├── lib.rs │ │ ├── snapshots │ │ │ ├── obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__webhook.snap │ │ │ ├── obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__activity.snap │ │ │ ├── obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@stub__activity.snap │ │ │ ├── obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__workflow.snap │ │ │ ├── obeli_sk_utils__wasm_tools__tests__params@test_programs_fibo_workflow.wasm_exports.snap │ │ │ └── obeli_sk_utils__wasm_tools__tests__exports_imports@test_programs_fibo_workflow.wasm_exports_noext.snap │ │ ├── sha256sum.rs │ │ └── panic_hook.rs │ └── Cargo.toml ├── db-mem │ ├── src │ │ └── lib.rs │ └── Cargo.toml ├── wasm-workers │ ├── src │ │ ├── webhook │ │ │ └── mod.rs │ │ ├── activity │ │ │ ├── mod.rs │ │ │ └── snapshots │ │ │ │ ├── obeli_sk_wasm_workers__activity__activity_worker__tests__wasmtime_nosim__variant_with_optional_none.snap │ │ │ │ └── obeli_sk_wasm_workers__activity__activity_worker__tests__wasmtime_nosim__record_field_ordering.snap │ │ ├── workflow │ │ │ ├── mod.rs │ │ │ └── wasi │ │ │ │ ├── random.rs │ │ │ │ └── clocks.rs │ │ ├── epoch_ticker.rs │ │ └── component_logger.rs │ ├── host-wit-activity │ │ ├── deps │ │ │ ├── wasi_io@0.2.3 │ │ │ └── obelisk_activity@1.0.0 │ │ └── dummy.wit │ ├── host-wit-log │ │ ├── deps │ │ │ └── obelisk_log@1.0.0 │ │ └── dummy.wit │ ├── host-wit-workflow-wasi │ │ ├── deps │ │ │ ├── wasi_cli@0.2.3 │ │ │ ├── wasi_io@0.2.3 │ │ │ ├── wasi_clocks@0.2.3 │ │ │ ├── wasi_random@0.2.3 │ │ │ ├── wasi_sockets@0.2.3 │ │ │ └── wasi_filesystem@0.2.3 │ │ └── dummy.wit │ ├── host-wit-webhook │ │ ├── deps │ │ │ └── obelisk_types@4.0.0 │ │ └── dummy.wit │ ├── host-wit-workflow │ │ ├── deps │ │ │ ├── obelisk_types@4.0.0 │ │ │ └── obelisk_workflow@4.0.0 │ │ └── dummy.wit │ └── Cargo.toml ├── db-sqlite │ ├── src │ │ └── lib.rs │ └── Cargo.toml ├── testing │ ├── test-programs │ │ ├── dir │ │ │ └── activity │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ └── testing_dir │ │ │ │ ├── impl.wit │ │ │ │ └── testing_dir │ │ │ │ │ └── dir.wit │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ └── lib.rs │ │ ├── fibo │ │ │ ├── activity │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ └── testing_fibo │ │ │ │ │ ├── impl.wit │ │ │ │ │ ├── testing_fibo │ │ │ │ │ │ └── fibo.wit │ │ │ │ │ └── gen │ │ │ │ │ │ ├── testing_fibo-obelisk-schedule │ │ │ │ │ │ └── fibo-obelisk-schedule.wit │ │ │ │ │ │ └── testing_fibo-obelisk-ext │ │ │ │ │ │ └── fibo-obelisk-ext.wit │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ ├── workflow │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ ├── testing_fibo │ │ │ │ │ │ ├── testing_fibo-workflow │ │ │ │ │ │ ├── obelisk_log@1.0.0 │ │ │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ │ │ ├── obelisk_workflow@4.0.0 │ │ │ │ │ │ └── testing_fibo-obelisk-ext │ │ │ │ │ ├── testing_fibo-workflow │ │ │ │ │ │ └── ifc.wit │ │ │ │ │ ├── impl.wit │ │ │ │ │ └── gen │ │ │ │ │ │ ├── testing_fibo-workflow-obelisk-schedule │ │ │ │ │ │ └── fibo-workflow-obelisk-schedule.wit │ │ │ │ │ │ └── testing_fibo-workflow-obelisk-ext │ │ │ │ │ │ └── fibo-workflow-obelisk-ext.wit │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ ├── webhook │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ ├── obelisk_log@1.0.0 │ │ │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ │ │ ├── testing_fibo-workflow │ │ │ │ │ │ └── testing_fibo-workflow-obelisk-schedule │ │ │ │ │ └── impl.wit │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ └── workflow-outer │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ ├── obelisk_log@1.0.0 │ │ │ │ │ ├── testing_fibo-workflow-outer │ │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ │ ├── testing_fibo-workflow │ │ │ │ │ ├── obelisk_workflow@4.0.0 │ │ │ │ │ └── testing_fibo-workflow-obelisk-ext │ │ │ │ ├── testing_fibo-workflow-outer │ │ │ │ │ └── ifc.wit │ │ │ │ └── impl.wit │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ └── lib.rs │ │ ├── http │ │ │ ├── activity │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ ├── testing_http │ │ │ │ │ │ └── obelisk_log@1.0.0 │ │ │ │ │ ├── impl.wit │ │ │ │ │ ├── testing_http │ │ │ │ │ │ └── http-get.wit │ │ │ │ │ └── gen │ │ │ │ │ │ ├── testing_http-obelisk-schedule │ │ │ │ │ │ └── http-obelisk-schedule.wit │ │ │ │ │ │ └── testing_http-obelisk-ext │ │ │ │ │ │ └── http-obelisk-ext.wit │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ └── workflow │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ ├── testing:http-workflow │ │ │ │ │ ├── testing_http │ │ │ │ │ ├── obelisk_log@1.0.0 │ │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ │ ├── obelisk_workflow@4.0.0 │ │ │ │ │ └── testing_http-obelisk-ext │ │ │ │ ├── impl.wit │ │ │ │ └── testing:http-workflow │ │ │ │ │ └── workflow.wit │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ └── lib.rs │ │ ├── serde │ │ │ ├── activity │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ └── testing_serde │ │ │ │ │ ├── impl.wit │ │ │ │ │ └── testing_serde │ │ │ │ │ │ └── serde.wit │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ └── workflow │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ ├── testing_serde │ │ │ │ │ └── testing_serde-workflow │ │ │ │ ├── impl.wit │ │ │ │ └── testing_serde-workflow │ │ │ │ │ └── serde-workflow.wit │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ └── lib.rs │ │ ├── sleep │ │ │ ├── activity │ │ │ │ ├── wit │ │ │ │ │ ├── deps │ │ │ │ │ │ ├── testing_sleep │ │ │ │ │ │ └── obelisk_types@4.0.0 │ │ │ │ │ ├── impl.wit │ │ │ │ │ ├── testing_sleep │ │ │ │ │ │ └── sleep.wit │ │ │ │ │ └── gen │ │ │ │ │ │ ├── testing_sleep-obelisk-schedule │ │ │ │ │ │ └── sleep-obelisk-schedule.wit │ │ │ │ │ │ └── testing_sleep-obelisk-ext │ │ │ │ │ │ └── sleep-obelisk-ext.wit │ │ │ │ ├── builder │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ ├── build.rs │ │ │ │ │ └── Cargo.toml │ │ │ │ ├── Cargo.toml │ │ │ │ └── src │ │ │ │ │ └── lib.rs │ │ │ └── workflow │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ ├── testing_sleep │ │ │ │ │ ├── testing_sleep-workflow │ │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ │ ├── obelisk_workflow@4.0.0 │ │ │ │ │ ├── testing_sleep-obelisk-ext │ │ │ │ │ └── testing_sleep-obelisk-schedule │ │ │ │ ├── impl.wit │ │ │ │ └── testing_sleep-workflow │ │ │ │ │ └── sleep.wit │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ └── Cargo.toml │ │ ├── process │ │ │ └── activity │ │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ ├── testing_process │ │ │ │ │ ├── wasi_io@0.2.3 │ │ │ │ │ └── obelisk_activity@1.0.0 │ │ │ │ ├── impl.wit │ │ │ │ └── testing_process │ │ │ │ │ └── process.wit │ │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ │ └── Cargo.toml │ │ └── stub │ │ │ ├── activity │ │ │ ├── wit │ │ │ │ ├── deps │ │ │ │ │ └── testing_stub-activity │ │ │ │ ├── impl.wit │ │ │ │ ├── testing_stub-activity │ │ │ │ │ └── stub-activity.wit │ │ │ │ └── gen │ │ │ │ │ ├── testing_stub-activity-obelisk-stub │ │ │ │ │ └── stub-activity-obelisk-stub.wit │ │ │ │ │ └── testing_stub-activity-obelisk-ext │ │ │ │ │ └── stub-activity-obelisk-ext.wit │ │ │ ├── builder │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ ├── build.rs │ │ │ │ └── Cargo.toml │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ └── lib.rs │ │ │ └── workflow │ │ │ ├── wit │ │ │ ├── deps │ │ │ │ ├── testing_stub-workflow │ │ │ │ ├── obelisk_log@1.0.0 │ │ │ │ ├── obelisk_types@4.0.0 │ │ │ │ ├── testing_stub-activity │ │ │ │ ├── obelisk_workflow@4.0.0 │ │ │ │ ├── testing_stub-activity-obelisk-ext │ │ │ │ └── testing_stub-activity-obelisk-stub │ │ │ ├── impl.wit │ │ │ └── testing_stub-workflow │ │ │ │ └── stub-workflow.wit │ │ │ ├── builder │ │ │ ├── src │ │ │ │ └── lib.rs │ │ │ ├── build.rs │ │ │ └── Cargo.toml │ │ │ └── Cargo.toml │ ├── test-utils │ │ ├── Cargo.toml │ │ └── src │ │ │ ├── arbitrary.rs │ │ │ └── sim_clock.rs │ ├── component-builder │ │ └── Cargo.toml │ └── db-tests │ │ ├── Cargo.toml │ │ └── src │ │ └── lib.rs ├── val-json │ ├── src │ │ ├── lib.rs │ │ └── snapshots │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_bool.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_option_none.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_option_some.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_list.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_enum.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_variant_without_field.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_tuple.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_flags.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_result_err_none.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_none.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_some.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_result_err_some.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_record.snap │ │ │ ├── obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_option_none.snap │ │ │ └── obeli_sk_val_json__wast_val_ser__tests__serde_variant_with_field.snap │ └── Cargo.toml ├── concepts │ ├── src │ │ ├── snapshots │ │ │ ├── obeli_sk_concepts__storage__tests__join_set_deser_with_result_ok_option_none_should_work.snap │ │ │ └── obeli_sk_concepts__tests__execution_id_hash_should_be_stable.snap │ │ └── time.rs │ └── Cargo.toml ├── executor │ ├── src │ │ └── lib.rs │ └── Cargo.toml └── bench │ └── Cargo.toml ├── .ignore ├── src ├── server │ └── mod.rs ├── command │ ├── mod.rs │ └── termination_notifier.rs ├── env_vars.rs ├── config │ └── env_var.rs ├── main.rs └── config.rs ├── assets ├── images │ ├── logo-small.png │ └── screencast.gif └── webui-version.txt ├── .gitignore ├── .envrc-example ├── wit ├── wasi_cli@0.2.3 │ ├── run.wit │ ├── command.wit │ ├── stdio.wit │ ├── exit.wit │ ├── environment.wit │ ├── imports.wit │ └── terminal.wit ├── wasi_io@0.2.3 │ ├── world.wit │ ├── error.wit │ └── poll.wit ├── wasi_filesystem@0.2.3 │ ├── world.wit │ └── preopens.wit ├── wasi_random@0.2.3 │ ├── world.wit │ ├── insecure.wit │ ├── insecure-seed.wit │ └── random.wit ├── wasi_clocks@0.2.3 │ ├── world.wit │ ├── monotonic-clock.wit │ ├── wall-clock.wit │ └── timezone.wit ├── wasi_sockets@0.2.3 │ ├── instance-network.wit │ ├── world.wit │ ├── udp-create-socket.wit │ └── tcp-create-socket.wit ├── obelisk_log@1.0.0 │ └── log.wit ├── LICENSE-MIT └── obelisk_workflow@4.0.0 │ └── workflow-support.wit ├── scripts ├── update-toml-schema.sh ├── clippy.sh ├── test.sh ├── cargo-publish-workspace.sh ├── extract-release-info.sh ├── unpublishable-packages.sh ├── regenerate-wit-extensions.sh ├── dev-deps.sh └── push-test-components.sh ├── rust-toolchain.toml ├── garnix.yaml ├── .cargo └── config.toml ├── .github ├── workflows │ ├── release │ │ └── docker-image │ │ │ ├── alpine.Dockerfile │ │ │ ├── ubuntu-24.04.Dockerfile │ │ │ └── ubuntu-24.04-litestream.Dockerfile │ ├── audit.yml │ ├── codspeed.yml │ ├── check-extensions.yml │ ├── check-toml-schema.yml │ ├── check-test.yml │ ├── release-5-verify-cargo-install.yml │ ├── release-5-verify-github-release.yml │ ├── scheduled-bump-flake-lock.yml │ ├── release-2-cargo-publish.yml │ ├── release-3-create-github-release.yml │ ├── release-5-verify-run-nix.yml │ ├── check.yml │ └── scheduled-bump-cargo-lock.yml └── dependabot.yml ├── dev-deps.txt ├── rust-toolchain-cross.toml ├── .config └── nextest.toml ├── proto └── LICENSE-MIT ├── toml └── LICENSE-MIT ├── download.sh ├── flake.lock └── release-plz.toml /crates/grpc/proto: -------------------------------------------------------------------------------- 1 | ../../proto -------------------------------------------------------------------------------- /crates/utils/wit: -------------------------------------------------------------------------------- 1 | ../../wit -------------------------------------------------------------------------------- /.ignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .direnv/ 3 | -------------------------------------------------------------------------------- /crates/db-mem/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod inmemory_dao; 2 | mod journal; 3 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/webhook/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod webhook_trigger; 2 | -------------------------------------------------------------------------------- /crates/db-sqlite/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod histograms; 2 | pub mod sqlite_dao; 3 | -------------------------------------------------------------------------------- /src/server/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod grpc; 2 | pub(crate) mod web_api; 3 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/wit/deps/testing_dir: -------------------------------------------------------------------------------- 1 | ../testing_dir -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/wit/deps/testing_fibo: -------------------------------------------------------------------------------- 1 | ../testing_fibo -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/deps/testing_http: -------------------------------------------------------------------------------- 1 | ../testing_http -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/wit/deps/testing_serde: -------------------------------------------------------------------------------- 1 | ../testing_serde -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/deps/testing_sleep: -------------------------------------------------------------------------------- 1 | ../testing_sleep -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-activity/deps/wasi_io@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_io@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-log/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/wit/deps/testing_process: -------------------------------------------------------------------------------- 1 | ../testing_process/ -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_cli@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_cli@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_io@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_io@0.2.3 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/testing_fibo: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/testing_fibo -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/testing_fibo-workflow: -------------------------------------------------------------------------------- 1 | ../testing_fibo-workflow -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/testing:http-workflow: -------------------------------------------------------------------------------- 1 | ../testing:http-workflow -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/testing_http: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/testing_http -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/wit/deps/testing_stub-activity: -------------------------------------------------------------------------------- 1 | ../testing_stub-activity -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/testing_stub-workflow: -------------------------------------------------------------------------------- 1 | ../testing_stub-workflow -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-webhook/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_clocks@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_clocks@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_random@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_random@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/wit/deps/testing_serde: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/testing_serde -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/wit/deps/testing_serde-workflow: -------------------------------------------------------------------------------- 1 | ../testing_serde-workflow -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/testing_sleep: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/testing_sleep -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/testing_sleep-workflow: -------------------------------------------------------------------------------- 1 | ../testing_sleep-workflow -------------------------------------------------------------------------------- /crates/val-json/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod type_wrapper; 2 | pub mod wast_val; 3 | pub mod wast_val_ser; 4 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-activity/deps/obelisk_activity@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../wit/obelisk_activity@1.0.0 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_sockets@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_sockets@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /assets/images/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obeli-sk/obelisk/HEAD/assets/images/logo-small.png -------------------------------------------------------------------------------- /assets/images/screencast.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/obeli-sk/obelisk/HEAD/assets/images/screencast.gif -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/wit/deps/wasi_io@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/wasi_io@0.2.3 -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/deps/wasi_filesystem@0.2.3: -------------------------------------------------------------------------------- 1 | ../../../../wit/wasi_filesystem@0.2.3 -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod panic_hook; 2 | pub mod sha256sum; 3 | pub mod wasm_tools; 4 | pub mod wit; 5 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/wit/deps/testing_fibo-workflow: -------------------------------------------------------------------------------- 1 | ../../../workflow/wit/testing_fibo-workflow -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/obelisk_log@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_log@1.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/testing_fibo-workflow-outer: -------------------------------------------------------------------------------- 1 | ../testing_fibo-workflow-outer -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/builder/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/gen.rs")); 2 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/testing_stub-activity: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/testing_stub-activity -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/obelisk_types@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_types@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/testing_fibo-workflow: -------------------------------------------------------------------------------- 1 | ../../../workflow/wit/testing_fibo-workflow -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/obelisk_workflow@4.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_workflow@4.0.0 -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/deps/testing_fibo-obelisk-ext: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_fibo-obelisk-ext -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/deps/testing_http-obelisk-ext: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_http-obelisk-ext -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/wit/deps/obelisk_activity@1.0.0: -------------------------------------------------------------------------------- 1 | ../../../../../../../wit/obelisk_activity@1.0.0 -------------------------------------------------------------------------------- /assets/webui-version.txt: -------------------------------------------------------------------------------- 1 | docker.io/getobelisk/webui:2025-12-17@sha256:07bd1e7befa004ef503f4611aa0b5868184269169479a69d1f4573a884627a3d -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/testing_sleep-obelisk-ext: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_sleep-obelisk-ext -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:dir/dir; 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:fibo/fibo; 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.direnv/ 3 | /.envrc 4 | test-codegen-cache 5 | /assets/unpublishable-packages.txt 6 | /.vscode/ 7 | obelisk.log 8 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:serde/serde; 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:sleep/sleep; 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/deps/testing_sleep-obelisk-schedule: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_sleep-obelisk-schedule -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/testing_stub-activity-obelisk-ext: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_stub-activity-obelisk-ext -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/deps/testing_stub-activity-obelisk-stub: -------------------------------------------------------------------------------- 1 | ../../../activity/wit/gen/testing_stub-activity-obelisk-stub -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/wit/deps/testing_fibo-workflow-obelisk-schedule: -------------------------------------------------------------------------------- 1 | ../../../workflow/wit/gen/testing_fibo-workflow-obelisk-schedule -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/deps/testing_fibo-workflow-obelisk-ext: -------------------------------------------------------------------------------- 1 | ../../../workflow/wit/gen/testing_fibo-workflow-obelisk-ext -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:stub-activity/activity; 5 | } 6 | -------------------------------------------------------------------------------- /.envrc-example: -------------------------------------------------------------------------------- 1 | use flake . 2 | watch_file ./rust-toolchain.toml ./flake.nix 3 | 4 | export TRUNK_SKIP_VERSION_CHECK="true" 5 | export TRUNK_OFFLINE="true" 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/wit/testing_dir/dir.wit: -------------------------------------------------------------------------------- 1 | package testing:dir; 2 | 3 | interface dir { 4 | io: func() -> result<_, string>; 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/wit/testing_fibo/fibo.wit: -------------------------------------------------------------------------------- 1 | package testing:fibo; 2 | 3 | interface fibo { 4 | fibo: func(n: u8) -> result; 5 | } 6 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/activity/mod.rs: -------------------------------------------------------------------------------- 1 | mod activity_ctx; 2 | mod activity_ctx_process; 3 | pub mod activity_worker; 4 | pub mod cancel_registry; 5 | mod process; 6 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/run.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface run { 3 | /// Run the program. 4 | @since(version = 0.2.0) 5 | run: func() -> result; 6 | } 7 | -------------------------------------------------------------------------------- /scripts/update-toml-schema.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | cd "$(dirname "$0")/.." 5 | 6 | cargo run -- generate config-schema toml/schema.json 7 | -------------------------------------------------------------------------------- /src/command/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod component; 2 | pub(crate) mod execution; 3 | pub(crate) mod generate; 4 | pub(crate) mod server; 5 | pub(crate) mod termination_notifier; 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:http/http-get; 5 | import obelisk:log/log@1.0.0; 6 | } 7 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__webhook.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: snapshot 4 | --- 5 | 6 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.92" 3 | targets = ["wasm32-unknown-unknown", "wasm32-wasip2"] 4 | components = ["rustfmt", "clippy", "rust-src", "rust-analyzer", "cargo"] 5 | -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:process/process; 5 | 6 | import obelisk:activity/process@1.0.0; 7 | } 8 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:serde-workflow/serde-workflow; 5 | 6 | import testing:serde/serde; 7 | } 8 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-log/dummy.wit: -------------------------------------------------------------------------------- 1 | // We actually don't use this; it's just to let bindgen! find the corresponding world in wit/deps. 2 | package obelisk:any; 3 | 4 | world bindings { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /garnix.yaml: -------------------------------------------------------------------------------- 1 | builds: 2 | - branch: latest 3 | include: 4 | - "packages.x86_64-linux.default" 5 | 6 | - "packages.aarch64-linux.default" 7 | 8 | - "packages.aarch64-darwin.default" 9 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-activity/dummy.wit: -------------------------------------------------------------------------------- 1 | // We actually don't use this; it's just to let bindgen! find the corresponding world in wit/deps. 2 | package obelisk:any; 3 | 4 | world bindings { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-webhook/dummy.wit: -------------------------------------------------------------------------------- 1 | // We actually don't use this; it's just to let bindgen! find the corresponding world in wit/deps. 2 | package obelisk:any; 3 | 4 | world bindings { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow/dummy.wit: -------------------------------------------------------------------------------- 1 | // We actually don't use this; it's just to let bindgen! find the corresponding world in wit/deps. 2 | package obelisk:any; 3 | 4 | world bindings { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /crates/wasm-workers/host-wit-workflow-wasi/dummy.wit: -------------------------------------------------------------------------------- 1 | // We actually don't use this; it's just to let bindgen! find the corresponding world in wit/deps. 2 | package obelisk:any; 3 | 4 | world bindings { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/wit/testing_serde-workflow/serde-workflow.wit: -------------------------------------------------------------------------------- 1 | package testing:serde-workflow; 2 | 3 | interface serde-workflow { 4 | 5 | expect-trap: func() -> result; 6 | 7 | } 8 | 9 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | 3 | [env] 4 | CARGO_WORKSPACE_DIR = { value = "", relative = true } # remove once stable https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads 5 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_bool.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": "bool", 7 | "value": true 8 | } 9 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/command.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world command { 5 | @since(version = 0.2.0) 6 | include imports; 7 | 8 | @since(version = 0.2.0) 9 | export run; 10 | } 11 | -------------------------------------------------------------------------------- /wit/wasi_io@0.2.3/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import streams; 7 | 8 | @since(version = 0.2.0) 9 | import poll; 10 | } 11 | -------------------------------------------------------------------------------- /.github/workflows/release/docker-image/alpine.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | WORKDIR /obelisk 3 | ADD obelisk . 4 | ADD obelisk.toml /etc/obelisk/obelisk.toml 5 | ENV PATH="/obelisk:${PATH}" 6 | ENTRYPOINT ["obelisk"] 7 | CMD ["server", "run"] 8 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_workflow(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_activity(BuildConfig::target_subdir("release_testprograms")); 5 | } 6 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/wit/testing_stub-activity/stub-activity.wit: -------------------------------------------------------------------------------- 1 | package testing:stub-activity; 2 | 3 | interface activity { 4 | foo: func(arg: string) -> result; 5 | 6 | noret: func() -> result; 7 | } 8 | -------------------------------------------------------------------------------- /scripts/clippy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | cd "$(dirname "$0")/.." 5 | 6 | cargo clippy --workspace --all-targets --fix --allow-dirty --allow-staged -- -D warnings 7 | 8 | cargo fmt 9 | 10 | git status -s 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | import obelisk:log/log@1.0.0; 5 | import testing:fibo-workflow/workflow; 6 | import testing:fibo-workflow-obelisk-schedule/workflow; 7 | } 8 | -------------------------------------------------------------------------------- /wit/wasi_filesystem@0.2.3/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import types; 7 | @since(version = 0.2.0) 8 | import preopens; 9 | } 10 | -------------------------------------------------------------------------------- /.github/workflows/release/docker-image/ubuntu-24.04.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | WORKDIR /obelisk 3 | ADD obelisk . 4 | ADD obelisk.toml /etc/obelisk/obelisk.toml 5 | ENV PATH="/obelisk:${PATH}" 6 | ENTRYPOINT ["obelisk"] 7 | CMD ["server", "run"] 8 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/workflow/mod.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod caching_db_connection; 2 | pub mod deadline_tracker; 3 | pub(crate) mod event_history; 4 | pub mod host_exports; 5 | pub(crate) mod wasi; 6 | pub(crate) mod workflow_ctx; 7 | pub mod workflow_worker; 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: cargo 8 | directory: / 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/builder/build.rs: -------------------------------------------------------------------------------- 1 | use obelisk_component_builder::BuildConfig; 2 | 3 | fn main() { 4 | obelisk_component_builder::build_webhook_endpoint(BuildConfig::target_subdir( 5 | "release_testprograms", 6 | )); 7 | } 8 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_option_none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "option": "bool" 8 | }, 9 | "value": null 10 | } 11 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_option_some.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "option": "bool" 8 | }, 9 | "value": true 10 | } 11 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_list.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "list": "bool" 8 | }, 9 | "value": [ 10 | true 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_enum.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "enum": [ 8 | "a", 9 | "b" 10 | ] 11 | }, 12 | "value": "a" 13 | } 14 | -------------------------------------------------------------------------------- /crates/concepts/src/snapshots/obeli_sk_concepts__storage__tests__join_set_deser_with_result_ok_option_none_should_work.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/concepts/src/storage.rs 3 | expression: json 4 | --- 5 | {"Ok":{"ok":{"type":{"result":{"ok":{"option":"string"},"err":"string"}},"value":{"ok":null}}}} 6 | -------------------------------------------------------------------------------- /crates/concepts/src/snapshots/obeli_sk_concepts__tests__execution_id_hash_should_be_stable.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/concepts/src/lib.rs 3 | expression: vec 4 | --- 5 | [ 6 | 7784354942592584825, 7 | 11723254811987876837, 8 | 17595035818551879290, 9 | 5639045558307740638, 10 | ] 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/testing_fibo-workflow-outer/ifc.wit: -------------------------------------------------------------------------------- 1 | package testing:fibo-workflow-outer; 2 | 3 | interface workflow { 4 | fibo-nested-workflow: func(n: u8) -> result; 5 | fibo-start-fiboas: func(n: u8, fiboas: u32, iterations-per-fiboa: u32) -> result; 6 | } 7 | -------------------------------------------------------------------------------- /wit/wasi_random@0.2.3/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import random; 7 | 8 | @since(version = 0.2.0) 9 | import insecure; 10 | 11 | @since(version = 0.2.0) 12 | import insecure-seed; 13 | } 14 | -------------------------------------------------------------------------------- /wit/wasi_clocks@0.2.3/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import monotonic-clock; 7 | @since(version = 0.2.0) 8 | import wall-clock; 9 | @unstable(feature = clocks-timezone) 10 | import timezone; 11 | } 12 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_variant_without_field.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "variant": { 8 | "a": null, 9 | "b": null 10 | } 11 | }, 12 | "value": "a" 13 | } 14 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/testing_fibo-workflow/ifc.wit: -------------------------------------------------------------------------------- 1 | package testing:fibo-workflow; 2 | 3 | interface workflow { 4 | fibow: func(n: u8, iterations: u32) -> result; 5 | fiboa: func(n: u8, iterations: u32) -> result; 6 | fiboa-concurrent: func(n: u8, iterations: u32) -> result; 7 | } 8 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_tuple.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "tuple": [ 8 | "bool", 9 | "u32" 10 | ] 11 | }, 12 | "value": [ 13 | false, 14 | 1 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:fibo-workflow/workflow; 5 | 6 | import obelisk:log/log@1.0.0; 7 | import obelisk:workflow/workflow-support@4.0.0; 8 | 9 | import testing:fibo/fibo; 10 | import testing:fibo-obelisk-ext/fibo; 11 | } 12 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:http-workflow/workflow; 5 | 6 | import testing:http/http-get; 7 | import testing:http-obelisk-ext/http-get; 8 | import obelisk:workflow/workflow-support@4.0.0; 9 | import obelisk:log/log@1.0.0; 10 | } 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/testing_sleep/sleep.wit: -------------------------------------------------------------------------------- 1 | package testing:sleep; 2 | 3 | interface sleep { 4 | use obelisk:types/time@4.0.0.{duration}; 5 | 6 | sleep: func(duration: duration) -> result; 7 | sleep-loop: func(duration: duration, iterations: u32) -> result; 8 | noop: func() -> result; 9 | } 10 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_flags.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "flags": [ 8 | "a", 9 | "b", 10 | "c" 11 | ] 12 | }, 13 | "value": [ 14 | "a", 15 | "b" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_result_err_none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "result": { 8 | "ok": null, 9 | "err": null 10 | } 11 | }, 12 | "value": { 13 | "err": null 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "result": { 8 | "ok": null, 9 | "err": null 10 | } 11 | }, 12 | "value": { 13 | "ok": null 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_some.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "result": { 8 | "ok": "bool", 9 | "err": null 10 | } 11 | }, 12 | "value": { 13 | "ok": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Run regular tests. Use `--success-output=immediate` to print successful test output. 4 | 5 | set -exuo pipefail 6 | cd "$(dirname "$0")/.." 7 | 8 | RUST_BACKTRACE=1 \ 9 | RUST_LOG="${RUST_LOG:-obeli=debug,app=trace}" \ 10 | cargo nextest run --no-output-indent --workspace -P ci-test "$@" 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:sleep-workflow/workflow; 5 | import obelisk:workflow/workflow-support@4.0.0; 6 | 7 | import testing:sleep/sleep; 8 | import testing:sleep-obelisk-ext/sleep; 9 | import testing:sleep-obelisk-schedule/sleep; 10 | } 11 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_result_err_some.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "result": { 8 | "ok": "bool", 9 | "err": "string" 10 | } 11 | }, 12 | "value": { 13 | "err": "test" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_record.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "record": { 8 | "field1": "bool", 9 | "field2": "u32" 10 | } 11 | }, 12 | "value": { 13 | "field1": true, 14 | "field2": 1 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /wit/wasi_filesystem@0.2.3/preopens.wit: -------------------------------------------------------------------------------- 1 | package wasi:filesystem@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | interface preopens { 5 | @since(version = 0.2.0) 6 | use types.{descriptor}; 7 | 8 | /// Return the set of preopened directories, and their paths. 9 | @since(version = 0.2.0) 10 | get-directories: func() -> list>; 11 | } 12 | -------------------------------------------------------------------------------- /wit/wasi_sockets@0.2.3/instance-network.wit: -------------------------------------------------------------------------------- 1 | 2 | /// This interface provides a value-export of the default network handle.. 3 | @since(version = 0.2.0) 4 | interface instance-network { 5 | @since(version = 0.2.0) 6 | use network.{network}; 7 | 8 | /// Get a handle to the default network. 9 | @since(version = 0.2.0) 10 | instance-network: func() -> network; 11 | } 12 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_result_ok_option_none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "result": { 8 | "ok": { 9 | "option": "string" 10 | }, 11 | "err": "string" 12 | } 13 | }, 14 | "value": { 15 | "ok": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/grpc/src/grpc_gen.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::default_trait_access)] 2 | #![allow(clippy::struct_field_names)] 3 | #![allow(clippy::similar_names)] 4 | #![allow(clippy::wildcard_imports)] 5 | #![allow(clippy::doc_markdown)] 6 | #![allow(clippy::must_use_candidate)] 7 | tonic::include_proto!("obelisk"); 8 | 9 | pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("descriptor"); 10 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-dir-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-webhook-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-workflow-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/wit/testing_process/process.wit: -------------------------------------------------------------------------------- 1 | package testing:process; 2 | 3 | interface process { 4 | touch: func() -> result<_, string>; 5 | 6 | stdio: func() -> result<_, string>; 7 | 8 | kill: func() -> result<_, string>; 9 | 10 | exec-sleep: func() -> result; 11 | 12 | subscribe-wait: func() -> result<_, string>; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-serde-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-serde-workflow-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-sleep-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-sleep-workflow-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-stub-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-stub-workflow-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /.github/workflows/release/docker-image/ubuntu-24.04-litestream.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:24.04 2 | WORKDIR /obelisk 3 | 4 | ADD obelisk . 5 | ADD obelisk.toml /etc/obelisk/obelisk.toml 6 | 7 | # Install Litestream 8 | COPY --from=litestream/litestream:0.5.5 /usr/local/bin/litestream /usr/local/bin/litestream 9 | 10 | 11 | ENV PATH="/obelisk:${PATH}" 12 | ENTRYPOINT ["obelisk"] 13 | CMD ["server", "run"] 14 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/wit/gen/testing_fibo-obelisk-schedule/fibo-obelisk-schedule.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.25.1 2 | package testing:fibo-obelisk-schedule; 3 | 4 | interface fibo { 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | use obelisk:types/time@4.0.0.{schedule-at}; 7 | 8 | fibo-schedule: func(schedule-at: schedule-at, n: u8) -> execution-id; 9 | } 10 | 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-http-get-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-http-get-workflow-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-process-activity-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-workflow-outer-builder" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [build-dependencies] 12 | obelisk-component-builder.workspace = true 13 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:fibo-workflow-outer/workflow; 5 | 6 | import obelisk:log/log@1.0.0; 7 | import obelisk:workflow/workflow-support@4.0.0; 8 | 9 | import testing:fibo-workflow/workflow; 10 | import testing:fibo-workflow-obelisk-ext/workflow; 11 | import testing:fibo-workflow-outer/workflow; 12 | } 13 | -------------------------------------------------------------------------------- /dev-deps.txt: -------------------------------------------------------------------------------- 1 | cargo-binstall 1.16.4 2 | cargo-edit-upgrade 0.13.8 3 | cargo-expand 1.0.118 4 | cargo-insta 1.44.3 5 | cargo-nextest 0.9.114 6 | cargo-semver-checks 0.45.0 7 | litecli Version: 1.12.3 8 | nixpkgs-fmt 1.3.0 9 | pkg-config 0.29.2 10 | libprotoc 32.1 11 | rustc 1.92.0 (ded5c06cf 2025-12-08) 12 | wasm-tools 1.243.0 13 | wasmtime 39.0.1 14 | cargo-zigbuild 0.20.1 15 | litestream v0.5.5 16 | ldd (GNU libc) 2.40 17 | -------------------------------------------------------------------------------- /scripts/cargo-publish-workspace.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Publish all packages in the workspace except for those listed in assets/unpublishable-packages.txt. 4 | set -exuo pipefail 5 | cd "$(dirname "$0")/.." 6 | 7 | scripts/unpublishable-packages.sh 8 | 9 | EXCLUDE_PACKAGES=$(awk '{printf " --exclude %s", $1}' "assets/unpublishable-packages.txt") 10 | 11 | cargo publish --workspace ${EXCLUDE_PACKAGES[@]} "$@" 12 | -------------------------------------------------------------------------------- /rust-toolchain-cross.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.92" 3 | targets = [ 4 | "wasm32-unknown-unknown", 5 | "wasm32-wasip2", 6 | "aarch64-unknown-linux-gnu", 7 | "aarch64-unknown-linux-musl", 8 | "x86_64-unknown-linux-gnu", 9 | "x86_64-unknown-linux-musl", 10 | "x86_64-apple-darwin", 11 | "aarch64-apple-darwin", 12 | ] 13 | components = ["rustfmt", "clippy", "rust-src", "rust-analyzer", "cargo"] 14 | -------------------------------------------------------------------------------- /crates/val-json/src/snapshots/obeli_sk_val_json__wast_val_ser__tests__serde_variant_with_field.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/val-json/src/wast_val_ser.rs 3 | expression: json 4 | --- 5 | { 6 | "type": { 7 | "variant": { 8 | "milliseconds": "u64", 9 | "seconds": "u64", 10 | "minutes": "u32", 11 | "hours": "u32", 12 | "days": "u32" 13 | } 14 | }, 15 | "value": { 16 | "seconds": 1 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-dir-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-workflow" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-stub-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-stub-workflow" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-http-get-workflow" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-serde-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-serde-workflow" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-sleep-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-sleep-workflow" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /src/env_vars.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "tokio-console")] 2 | #[derive(strum::Display, Clone, Copy)] 3 | #[expect(non_camel_case_types)] 4 | pub(crate) enum SupportedEnvVar { 5 | TOKIO_CONSOLE, 6 | } 7 | 8 | #[cfg(feature = "tokio-console")] 9 | pub(crate) fn is_env_true(key: &SupportedEnvVar) -> bool { 10 | std::env::var(key.to_string()) 11 | .ok() 12 | .and_then(|val| val.parse::().ok()) 13 | .unwrap_or_default() 14 | } 15 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-workflow-outer" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | 14 | [lib] 15 | crate-type = ["cdylib"] 16 | 17 | [lints] 18 | workspace = true 19 | -------------------------------------------------------------------------------- /wit/obelisk_log@1.0.0/log.wit: -------------------------------------------------------------------------------- 1 | package obelisk:log@1.0.0; 2 | 3 | @since(version = 1.0.0) 4 | interface log { 5 | @since(version = 1.0.0) 6 | trace: func(message: string); 7 | @since(version = 1.0.0) 8 | debug: func(message: string); 9 | @since(version = 1.0.0) 10 | info: func(message: string); 11 | @since(version = 1.0.0) 12 | warn: func(message: string); 13 | @since(version = 1.0.0) 14 | error: func(message: string); 15 | } 16 | -------------------------------------------------------------------------------- /crates/executor/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod executor; 2 | pub mod expired_timers_watcher; 3 | pub mod worker; 4 | 5 | use tokio::task::AbortHandle; 6 | 7 | pub struct AbortOnDropHandle { 8 | handle: AbortHandle, 9 | } 10 | impl AbortOnDropHandle { 11 | #[must_use] 12 | pub fn new(handle: AbortHandle) -> Self { 13 | Self { handle } 14 | } 15 | } 16 | impl Drop for AbortOnDropHandle { 17 | fn drop(&mut self) { 18 | self.handle.abort(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.config/nextest.toml: -------------------------------------------------------------------------------- 1 | [profile.ci-test] 2 | failure-output = "immediate" 3 | fail-fast = false 4 | status-level = "all" 5 | slow-timeout = { period = "10s", terminate-after = 4 } 6 | junit.path = "junit.xml" 7 | junit.report-name = "ci-test" 8 | junit.store-success-output = true 9 | junit.store-failure-output = true 10 | 11 | [profile.ci-test-populate-codegen-cache] 12 | failure-output = "immediate" 13 | fail-fast = true 14 | status-level = "all" 15 | slow-timeout = { period = "10s", terminate-after = 4 } 16 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-fibo-webhook" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | wit-bindgen.workspace = true 13 | waki.workspace = true 14 | waki-macros.workspace = true 15 | 16 | [lib] 17 | crate-type = ["cdylib"] 18 | 19 | [lints] 20 | workspace = true 21 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-http-get-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | anyhow.workspace = true 13 | waki.workspace = true 14 | wit-bindgen.workspace = true 15 | 16 | [lib] 17 | crate-type = ["cdylib"] 18 | 19 | [lints] 20 | workspace = true 21 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/impl.wit: -------------------------------------------------------------------------------- 1 | package any:any; 2 | 3 | world any { 4 | export testing:stub-workflow/workflow; 5 | import testing:stub-activity-obelisk-ext/activity; // for submitting the execution 6 | import testing:stub-activity-obelisk-stub/activity; // for submitting the execution result 7 | import testing:stub-activity/activity; // for direct call 8 | import obelisk:workflow/workflow-support@4.0.0; 9 | import obelisk:log/log@1.0.0; 10 | } 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::fibo::fibo::Guest; 2 | use wit_bindgen::generate; 3 | 4 | generate!({ generate_all }); 5 | struct Component; 6 | export!(Component); 7 | 8 | impl Guest for Component { 9 | fn fibo(n: u8) -> Result { 10 | Ok(fibo(n)) 11 | } 12 | } 13 | 14 | fn fibo(n: u8) -> u64 { 15 | if n == 0 { 16 | 0 17 | } else if n == 1 { 18 | 1 19 | } else { 20 | fibo(n - 1) + fibo(n - 2) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::stub_activity::activity::Guest; 2 | use wit_bindgen::generate; 3 | 4 | generate!({ generate_all }); 5 | struct Component; 6 | export!(Component); 7 | 8 | impl Guest for Component { 9 | fn foo(_arg: String) -> Result { 10 | unimplemented!("actual implementation is never used") 11 | } 12 | 13 | fn noret() -> Result<(), ()> { 14 | unimplemented!("actual implementation is never used") 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/wit/gen/testing_stub-activity-obelisk-stub/stub-activity-obelisk-stub.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.25.1 2 | package testing:stub-activity-obelisk-stub; 3 | 4 | interface activity { 5 | use obelisk:types/execution@4.0.0.{execution-id, stub-error}; 6 | 7 | foo-stub: func(execution-id: execution-id, execution-result: result) -> result<_, stub-error>; 8 | 9 | noret-stub: func(execution-id: execution-id, execution-result: result) -> result<_, stub-error>; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /wit/wasi_sockets@0.2.3/world.wit: -------------------------------------------------------------------------------- 1 | package wasi:sockets@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | import instance-network; 7 | @since(version = 0.2.0) 8 | import network; 9 | @since(version = 0.2.0) 10 | import udp; 11 | @since(version = 0.2.0) 12 | import udp-create-socket; 13 | @since(version = 0.2.0) 14 | import tcp; 15 | @since(version = 0.2.0) 16 | import tcp-create-socket; 17 | @since(version = 0.2.0) 18 | import ip-name-lookup; 19 | } 20 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/workflow/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate::exports::testing::serde_workflow::serde_workflow::Guest; 2 | use testing::serde::serde::{self, MyError}; 3 | use wit_bindgen::generate; 4 | 5 | generate!({ generate_all }); 6 | struct Component; 7 | export!(Component); 8 | 9 | impl Guest for Component { 10 | fn expect_trap() -> Result<(), ()> { 11 | let err = serde::trap().unwrap_err(); 12 | let MyError::ExecutionFailed = err else { 13 | panic!("wrong error {err:?}"); 14 | }; 15 | Ok(()) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::serde::serde::{Guest, MyError, MyRecord, MyVariant}; 2 | use wit_bindgen::generate; 3 | 4 | generate!({ generate_all }); 5 | struct Component; 6 | export!(Component); 7 | 8 | impl Guest for Component { 9 | fn rec(my_record: MyRecord) -> Result { 10 | Ok(my_record) 11 | } 12 | 13 | fn var(my_variant: MyVariant) -> Result { 14 | Ok(my_variant) 15 | } 16 | 17 | fn trap() -> Result<(), MyError> { 18 | panic!() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/wit/testing:http-workflow/workflow.wit: -------------------------------------------------------------------------------- 1 | package testing:http-workflow; 2 | 3 | interface workflow { 4 | get: func(url: string) -> result; 5 | get-resp: func(url: string) -> result; 6 | get-stargazers: func() -> result; 7 | get-successful: func(url: string) -> result; 8 | get-successful-concurrently: func(urls: list) -> result, string>; 9 | get-successful-concurrently-stress: func(url: string, concurrency: u32) -> result, string>; 10 | } 11 | -------------------------------------------------------------------------------- /crates/testing/test-programs/process/activity/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-programs-process-activity" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | anyhow.workspace = true 13 | futures-concurrency.workspace = true 14 | wasip2.workspace = true 15 | wit-bindgen.workspace = true 16 | wstd.workspace = true 17 | 18 | [lib] 19 | crate-type = ["cdylib"] 20 | 21 | [lints] 22 | workspace = true 23 | -------------------------------------------------------------------------------- /crates/testing/test-utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "test-utils" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | concepts.workspace = true 13 | utils.workspace = true 14 | 15 | arbitrary.workspace = true 16 | chrono.workspace = true 17 | rand.workspace = true 18 | tokio.workspace = true 19 | tracing.workspace = true 20 | tracing-subscriber.workspace = true 21 | 22 | [lints] 23 | workspace = true 24 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/testing_http/http-get.wit: -------------------------------------------------------------------------------- 1 | package testing:http; 2 | 3 | interface http-get { 4 | 5 | record response { 6 | body: list, 7 | status-code: u16, 8 | } 9 | 10 | 11 | record stargazers { 12 | logins: string, 13 | cursor: string, 14 | } 15 | 16 | get: func(url: string) -> result; 17 | get-resp: func(url: string) -> result; 18 | get-stargazers: func() -> result; 19 | get-successful: func(url: string) -> result; 20 | } 21 | -------------------------------------------------------------------------------- /crates/testing/test-programs/serde/activity/wit/testing_serde/serde.wit: -------------------------------------------------------------------------------- 1 | package testing:serde; 2 | 3 | interface serde { 4 | 5 | record my-record { 6 | a: bool, 7 | image: string, 8 | b: bool, 9 | opt: option, 10 | } 11 | 12 | rec: func(my-record: my-record) -> result; 13 | 14 | variant my-variant { 15 | var1(option) 16 | } 17 | 18 | var: func(my-variant: my-variant) -> result; 19 | 20 | variant my-error { 21 | foo, 22 | execution-failed 23 | } 24 | trap: func() -> result<_, my-error>; 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /scripts/extract-release-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Called by the release CI job to extract the changelog section for a given version. 4 | # Usage: ./scripts/extract-release-info.sh 5 | 6 | set -exuo pipefail 7 | cd "$(dirname "$0")/.." 8 | 9 | if [ -z "$1" ]; then 10 | echo "Usage: $0 " 11 | exit 1 12 | fi 13 | 14 | VERSION="$1" 15 | 16 | START_LINE=$(awk -v version="$VERSION" '$0 ~ "^## \\[" version "\\]" {print NR}' CHANGELOG.md) 17 | 18 | END_LINE=$(awk -v start="$((START_LINE + 1))" 'NR >= start && /^## / {print NR; exit}' CHANGELOG.md) 19 | 20 | sed -n "$((START_LINE + 1)),$((END_LINE - 1))p" CHANGELOG.md 21 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/gen/testing_fibo-workflow-obelisk-schedule/fibo-workflow-obelisk-schedule.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.25.1 2 | package testing:fibo-workflow-obelisk-schedule; 3 | 4 | interface workflow { 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | use obelisk:types/time@4.0.0.{schedule-at}; 7 | 8 | fibow-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 9 | 10 | fiboa-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 11 | 12 | fiboa-concurrent-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/gen/testing_sleep-obelisk-schedule/sleep-obelisk-schedule.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.25.1 2 | package testing:sleep-obelisk-schedule; 3 | 4 | interface sleep { 5 | use obelisk:types/time@4.0.0.{duration}; 6 | use obelisk:types/execution@4.0.0.{execution-id}; 7 | use obelisk:types/time@4.0.0.{schedule-at}; 8 | 9 | sleep-schedule: func(schedule-at: schedule-at, duration: duration) -> execution-id; 10 | 11 | sleep-loop-schedule: func(schedule-at: schedule-at, duration: duration, iterations: u32) -> execution-id; 12 | 13 | noop-schedule: func(schedule-at: schedule-at) -> execution-id; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/stdio.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface stdin { 3 | @since(version = 0.2.0) 4 | use wasi:io/streams@0.2.3.{input-stream}; 5 | 6 | @since(version = 0.2.0) 7 | get-stdin: func() -> input-stream; 8 | } 9 | 10 | @since(version = 0.2.0) 11 | interface stdout { 12 | @since(version = 0.2.0) 13 | use wasi:io/streams@0.2.3.{output-stream}; 14 | 15 | @since(version = 0.2.0) 16 | get-stdout: func() -> output-stream; 17 | } 18 | 19 | @since(version = 0.2.0) 20 | interface stderr { 21 | @since(version = 0.2.0) 22 | use wasi:io/streams@0.2.3.{output-stream}; 23 | 24 | @since(version = 0.2.0) 25 | get-stderr: func() -> output-stream; 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/audit.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | paths: 7 | - "**/Cargo.toml" 8 | - "**/Cargo.lock" 9 | - ".github/workflows/audit.yml" 10 | schedule: 11 | - cron: "0 0 * * *" 12 | 13 | jobs: 14 | security_audit: 15 | name: Audit check 16 | runs-on: ubuntu-24.04 17 | permissions: 18 | checks: write 19 | contents: read 20 | issues: write 21 | steps: 22 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 23 | - uses: rustsec/audit-check@69366f33c96575abad1ee0dba8212993eecbe998 24 | with: 25 | token: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /crates/testing/component-builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obelisk-component-builder" 3 | description = "Builder of Obelisk components" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | publish = false 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | version.workspace = true 12 | 13 | [dependencies] 14 | concepts = { workspace = true, optional = true } 15 | utils = { workspace = true, optional = true } 16 | 17 | cargo_metadata.workspace = true 18 | indexmap = { workspace = true, optional = true } 19 | 20 | [features] 21 | genrs = ["dep:concepts", "dep:utils", "dep:indexmap"] 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/activity/wit/gen/testing_fibo-obelisk-ext/fibo-obelisk-ext.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.31.0-dev 2 | package testing:fibo-obelisk-ext; 3 | 4 | interface fibo { 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | use obelisk:types/join-set@4.0.0.{join-set}; 7 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 8 | 9 | fibo-submit: func(join-set: borrow, n: u8) -> execution-id; 10 | 11 | fibo-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 12 | 13 | fibo-get: func(execution-id: execution-id) -> result, get-extension-error>; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/activity/snapshots/obeli_sk_wasm_workers__activity__activity_worker__tests__wasmtime_nosim__variant_with_optional_none.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/wasm-workers/src/activity/activity_worker.rs 3 | expression: variant 4 | --- 5 | Some( 6 | WastValWithType { 7 | type: Variant( 8 | { 9 | "var1": Some( 10 | Option( 11 | Bool, 12 | ), 13 | ), 14 | }, 15 | ), 16 | value: Variant( 17 | "var1", 18 | Some( 19 | Option( 20 | None, 21 | ), 22 | ), 23 | ), 24 | }, 25 | ) 26 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/gen/testing_http-obelisk-schedule/http-obelisk-schedule.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.25.1 2 | package testing:http-obelisk-schedule; 3 | 4 | interface http-get { 5 | use testing:http/http-get.{response, stargazers}; 6 | use obelisk:types/execution@4.0.0.{execution-id}; 7 | use obelisk:types/time@4.0.0.{schedule-at}; 8 | 9 | get-schedule: func(schedule-at: schedule-at, url: string) -> execution-id; 10 | 11 | get-resp-schedule: func(schedule-at: schedule-at, url: string) -> execution-id; 12 | 13 | get-stargazers-schedule: func(schedule-at: schedule-at) -> execution-id; 14 | 15 | get-successful-schedule: func(schedule-at: schedule-at, url: string) -> execution-id; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/exit.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface exit { 3 | /// Exit the current instance and any linked instances. 4 | @since(version = 0.2.0) 5 | exit: func(status: result); 6 | 7 | /// Exit the current instance and any linked instances, reporting the 8 | /// specified status code to the host. 9 | /// 10 | /// The meaning of the code depends on the context, with 0 usually meaning 11 | /// "success", and other values indicating various types of failure. 12 | /// 13 | /// This function does not return; the effect is analogous to a trap, but 14 | /// without the connotation that something bad has happened. 15 | @unstable(feature = cli-exit-with-code) 16 | exit-with-code: func(status-code: u8); 17 | } 18 | -------------------------------------------------------------------------------- /crates/utils/src/sha256sum.rs: -------------------------------------------------------------------------------- 1 | use concepts::{ContentDigest, component_id::Digest}; 2 | use std::path::Path; 3 | 4 | #[tracing::instrument(skip_all)] 5 | pub async fn calculate_sha256_file>( 6 | path: P, 7 | ) -> Result { 8 | use sha2::Digest; 9 | use tokio::io::AsyncReadExt; 10 | let mut file = tokio::fs::File::open(path).await?; 11 | let mut hasher = sha2::Sha256::default(); 12 | let mut buf = [0; 4096]; 13 | loop { 14 | let n = file.read(&mut buf).await?; 15 | if n == 0 { 16 | break; 17 | } 18 | hasher.update(&buf[..n]); 19 | } 20 | let digest: [u8; 32] = hasher.finalize().into(); 21 | Ok(ContentDigest(Digest(digest))) 22 | } 23 | -------------------------------------------------------------------------------- /crates/db-mem/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "db-mem" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | concepts.workspace = true 13 | utils.workspace = true 14 | val-json.workspace = true 15 | 16 | arbitrary.workspace = true 17 | assert_matches.workspace = true 18 | async-trait.workspace = true 19 | chrono.workspace = true 20 | derive_more.workspace = true 21 | hashbrown.workspace = true 22 | itertools.workspace = true 23 | thiserror.workspace = true 24 | tokio.workspace = true 25 | tracing.workspace = true 26 | 27 | [features] 28 | test = [] 29 | 30 | [lints] 31 | workspace = true 32 | -------------------------------------------------------------------------------- /crates/testing/test-utils/src/arbitrary.rs: -------------------------------------------------------------------------------- 1 | use rand::{Rng, SeedableRng as _, rngs::StdRng}; 2 | 3 | pub struct UnstructuredHolder { 4 | raw_data: Vec, 5 | } 6 | 7 | impl UnstructuredHolder { 8 | #[must_use] 9 | pub fn new(seed: u64) -> Self { 10 | let mut seedable_rng = StdRng::seed_from_u64(seed); 11 | let len = seedable_rng.random::() as usize; 12 | let mut raw_data = Vec::with_capacity(len); 13 | while raw_data.len() < len { 14 | raw_data.push(seedable_rng.random::()); 15 | } 16 | Self { raw_data } 17 | } 18 | 19 | #[must_use] 20 | pub fn unstructured(&self) -> arbitrary::Unstructured<'_> { 21 | arbitrary::Unstructured::new(&self.raw_data) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /scripts/unpublishable-packages.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Find all packages with "publish = false" in their Cargo.toml files and save them to a file. 4 | 5 | set -exuo pipefail 6 | cd "$(dirname "$0")/.." 7 | 8 | OUTPUT_FILE="assets/unpublishable-packages.txt" 9 | 10 | # Find all Cargo.toml files and check if "publish = false" is set 11 | PACKAGES=() 12 | while IFS= read -r file; do 13 | PACKAGE_NAME=$(grep -m1 '^name\s*=\s*"' "$file" | sed -E 's/name\s*=\s*"([^"]+)"/\1/') 14 | if [ -n "$PACKAGE_NAME" ]; then 15 | PACKAGES+=("$PACKAGE_NAME") 16 | fi 17 | done < <(grep -rl "publish\s*=\s*false" --include="Cargo.toml" crates) 18 | 19 | # Sort and write to file 20 | printf "%s\n" "${PACKAGES[@]}" | sort > "$OUTPUT_FILE" 21 | 22 | echo "Unpublishable packages saved to $OUTPUT_FILE" 23 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/workflow/wit/testing_sleep-workflow/sleep.wit: -------------------------------------------------------------------------------- 1 | package testing:sleep-workflow; 2 | 3 | interface workflow { 4 | use obelisk:types/time@4.0.0.{duration, schedule-at}; 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | 7 | sleep-host-activity: func(duration: duration) -> result; 8 | sleep-schedule-at: func(schedule-at: schedule-at) -> result; 9 | sleep-activity: func(duration: duration) -> result; 10 | sleep-activity-submit: func(duration: duration) -> result; 11 | sleep-random: func(min-millis: u64, max-millis-inclusive: u64) -> result; 12 | schedule-noop: func(duration: duration) -> result; 13 | 14 | two-delays-in-same-join-set: func() -> result; 15 | join-next-produces-all-processed-error: func() -> result; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/workflow/wit/testing_stub-workflow/stub-workflow.wit: -------------------------------------------------------------------------------- 1 | package testing:stub-workflow; 2 | 3 | interface workflow { 4 | use obelisk:types/execution@4.0.0.{execution-id}; 5 | 6 | submit-stub-await: func(arg: string) -> result; 7 | submit-await: func(arg: string) -> result; 8 | 9 | noret-submit-await: func() -> result; 10 | 11 | submit-race-join-next-stub: func() -> result; 12 | submit-race-join-next-stub-error: func() -> result; 13 | submit-race-join-next-delay: func() -> result; 14 | 15 | stub-subworkflow: func(execution-id: execution-id, retval: string) -> result; 16 | 17 | await-next-produces-all-processed-error: func() -> result; 18 | 19 | join-next-in-scope: func() -> result; 20 | 21 | invoke-expect-execution-error: func() -> result; 22 | } 23 | -------------------------------------------------------------------------------- /src/command/termination_notifier.rs: -------------------------------------------------------------------------------- 1 | use tokio::{signal, sync::watch}; 2 | use tracing::warn; 3 | 4 | pub(crate) async fn termination_notifier(termination_sender: watch::Sender) { 5 | let ctrl_c = async { 6 | signal::ctrl_c() 7 | .await 8 | .expect("failed to install Ctrl+C handler"); 9 | }; 10 | 11 | #[cfg(unix)] 12 | let terminate = async { 13 | signal::unix::signal(signal::unix::SignalKind::terminate()) 14 | .expect("failed to install signal handler") 15 | .recv() 16 | .await; 17 | }; 18 | 19 | #[cfg(not(unix))] 20 | let terminate = std::future::pending::<()>(); 21 | 22 | tokio::select! { 23 | () = ctrl_c => {}, 24 | () = terminate => {}, 25 | } 26 | 27 | warn!("Received shutdown signal"); 28 | drop(termination_sender); 29 | } 30 | -------------------------------------------------------------------------------- /crates/concepts/src/time.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use chrono::DateTime; 3 | use chrono::Utc; 4 | use std::time::Duration; 5 | 6 | pub trait ClockFn: Send + Sync + Clone + 'static { 7 | fn now(&self) -> DateTime; 8 | } 9 | 10 | #[async_trait] 11 | pub trait Sleep: Send + Sync + Clone + 'static { 12 | async fn sleep(&self, duration: Duration); 13 | } 14 | 15 | #[derive(Clone)] 16 | pub struct TokioSleep; 17 | 18 | #[async_trait] 19 | impl Sleep for TokioSleep { 20 | async fn sleep(&self, duration: Duration) { 21 | tokio::time::sleep(duration).await; 22 | } 23 | } 24 | 25 | #[must_use] 26 | pub fn now_tokio_instant() -> tokio::time::Instant { 27 | tokio::time::Instant::now() 28 | } 29 | 30 | #[derive(Clone)] 31 | pub struct Now; 32 | 33 | impl ClockFn for Now { 34 | fn now(&self) -> DateTime { 35 | Utc::now() 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/codspeed.yml: -------------------------------------------------------------------------------- 1 | name: CodSpeed 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | benchmarks: 8 | name: Run benchmarks 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v6.0.1 12 | 13 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 14 | with: 15 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 16 | - name: Populate the nix store 17 | run: nix develop --command echo 18 | 19 | - name: Build the benchmark target(s) 20 | run: nix develop --command cargo codspeed build -p bench --jobs 1 21 | 22 | - name: Run benchmarks 23 | uses: CodSpeedHQ/action@v4 24 | with: 25 | token: ${{ secrets.CODSPEED_TOKEN }} 26 | run: nix develop --command cargo codspeed run -p bench 27 | env: 28 | RUST_BACKTRACE: 1 29 | -------------------------------------------------------------------------------- /crates/val-json/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-val-json" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | anyhow.workspace = true 14 | hashbrown.workspace = true 15 | indexmap.workspace = true 16 | itertools.workspace = true 17 | serde_json.workspace = true 18 | serde.workspace = true 19 | thiserror.workspace = true 20 | wasmtime = { workspace = true, optional = true } 21 | wast.workspace = true 22 | wit-parser = { workspace = true, optional = true } 23 | 24 | [dev-dependencies] 25 | assert_matches.workspace = true 26 | insta.workspace = true 27 | 28 | [features] 29 | wasmtime = ["dep:wasmtime"] 30 | wit-parser = ["dep:wit-parser"] 31 | 32 | [lints] 33 | workspace = true 34 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/environment.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface environment { 3 | /// Get the POSIX-style environment variables. 4 | /// 5 | /// Each environment variable is provided as a pair of string variable names 6 | /// and string value. 7 | /// 8 | /// Morally, these are a value import, but until value imports are available 9 | /// in the component model, this import function should return the same 10 | /// values each time it is called. 11 | @since(version = 0.2.0) 12 | get-environment: func() -> list>; 13 | 14 | /// Get the POSIX-style arguments to the program. 15 | @since(version = 0.2.0) 16 | get-arguments: func() -> list; 17 | 18 | /// Return a path that programs should use as their initial current working 19 | /// directory, interpreting `.` as shorthand for this. 20 | @since(version = 0.2.0) 21 | initial-cwd: func() -> option; 22 | } 23 | -------------------------------------------------------------------------------- /crates/testing/db-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "db-tests" 3 | authors.workspace = true 4 | edition.workspace = true 5 | license.workspace = true 6 | publish = false 7 | repository.workspace = true 8 | rust-version.workspace = true 9 | version.workspace = true 10 | 11 | [dependencies] 12 | concepts = { workspace = true, features = ["test"] } 13 | db-mem = { workspace = true, features = ["test"] } 14 | db-sqlite = { workspace = true, features = ["tempfile", "test"] } 15 | test-utils.workspace = true 16 | utils.workspace = true 17 | val-json.workspace = true 18 | 19 | arbitrary.workspace = true 20 | assert_matches.workspace = true 21 | async-trait.workspace = true 22 | chrono.workspace = true 23 | rand.workspace = true 24 | serde_json.workspace = true 25 | tempfile.workspace = true 26 | tokio.workspace = true 27 | tracing.workspace = true 28 | 29 | [dev-dependencies] 30 | rstest.workspace = true 31 | 32 | [lints] 33 | workspace = true 34 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/activity/snapshots/obeli_sk_wasm_workers__activity__activity_worker__tests__wasmtime_nosim__record_field_ordering.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/wasm-workers/src/activity/activity_worker.rs 3 | expression: record 4 | --- 5 | Some( 6 | WastValWithType { 7 | type: Record( 8 | { 9 | "a": Bool, 10 | "image": String, 11 | "b": Bool, 12 | "opt": Option( 13 | Bool, 14 | ), 15 | }, 16 | ), 17 | value: Record( 18 | { 19 | "a": Bool( 20 | false, 21 | ), 22 | "image": String( 23 | "foo", 24 | ), 25 | "b": Bool( 26 | false, 27 | ), 28 | "opt": Option( 29 | None, 30 | ), 31 | }, 32 | ), 33 | }, 34 | ) 35 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/imports.wit: -------------------------------------------------------------------------------- 1 | package wasi:cli@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | world imports { 5 | @since(version = 0.2.0) 6 | include wasi:clocks/imports@0.2.3; 7 | @since(version = 0.2.0) 8 | include wasi:filesystem/imports@0.2.3; 9 | @since(version = 0.2.0) 10 | include wasi:sockets/imports@0.2.3; 11 | @since(version = 0.2.0) 12 | include wasi:random/imports@0.2.3; 13 | @since(version = 0.2.0) 14 | include wasi:io/imports@0.2.3; 15 | 16 | @since(version = 0.2.0) 17 | import environment; 18 | @since(version = 0.2.0) 19 | import exit; 20 | @since(version = 0.2.0) 21 | import stdin; 22 | @since(version = 0.2.0) 23 | import stdout; 24 | @since(version = 0.2.0) 25 | import stderr; 26 | @since(version = 0.2.0) 27 | import terminal-input; 28 | @since(version = 0.2.0) 29 | import terminal-output; 30 | @since(version = 0.2.0) 31 | import terminal-stdin; 32 | @since(version = 0.2.0) 33 | import terminal-stdout; 34 | @since(version = 0.2.0) 35 | import terminal-stderr; 36 | } 37 | -------------------------------------------------------------------------------- /crates/testing/test-programs/stub/activity/wit/gen/testing_stub-activity-obelisk-ext/stub-activity-obelisk-ext.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.31.0-dev 2 | package testing:stub-activity-obelisk-ext; 3 | 4 | interface activity { 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | use obelisk:types/join-set@4.0.0.{join-set}; 7 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 8 | 9 | foo-submit: func(join-set: borrow, arg: string) -> execution-id; 10 | 11 | foo-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 12 | 13 | foo-get: func(execution-id: execution-id) -> result, get-extension-error>; 14 | 15 | noret-submit: func(join-set: borrow) -> execution-id; 16 | 17 | noret-await-next: func(join-set: borrow) -> result, await-next-extension-error>; 18 | 19 | noret-get: func(execution-id: execution-id) -> result; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /crates/bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bench" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | publish = false 9 | repository.workspace = true 10 | rust-version.workspace = true 11 | version.workspace = true 12 | 13 | [dependencies] 14 | 15 | [dev-dependencies] 16 | concepts = { workspace = true, features = ["test"] } 17 | db-sqlite = { workspace = true, features = ["tempfile"] } 18 | db-tests.workspace = true 19 | executor = { workspace = true, features = ["test"] } 20 | test-programs-fibo-activity-builder.workspace = true 21 | test-programs-fibo-workflow-builder.workspace = true 22 | test-utils.workspace = true 23 | utils.workspace = true 24 | wasm-workers = { workspace = true, features = ["test"] } 25 | 26 | assert_matches.workspace = true 27 | tokio.workspace = true 28 | wasmtime.workspace = true 29 | divan.workspace = true 30 | serde_json.workspace = true 31 | 32 | [[bench]] 33 | name = "fibo" 34 | harness = false 35 | 36 | [lints] 37 | workspace = true 38 | -------------------------------------------------------------------------------- /wit/wasi_random@0.2.3/insecure.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.3; 2 | /// The insecure interface for insecure pseudo-random numbers. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure { 8 | /// Return `len` insecure pseudo-random bytes. 9 | /// 10 | /// This function is not cryptographically secure. Do not use it for 11 | /// anything related to security. 12 | /// 13 | /// There are no requirements on the values of the returned bytes, however 14 | /// implementations are encouraged to return evenly distributed values with 15 | /// a long period. 16 | @since(version = 0.2.0) 17 | get-insecure-random-bytes: func(len: u64) -> list; 18 | 19 | /// Return an insecure pseudo-random `u64` value. 20 | /// 21 | /// This function returns the same type of pseudo-random data as 22 | /// `get-insecure-random-bytes`, represented as a `u64`. 23 | @since(version = 0.2.0) 24 | get-insecure-random-u64: func() -> u64; 25 | } 26 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__activity.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: snapshot 4 | --- 5 | testing:fibo-obelisk-ext 6 | package testing:fibo-obelisk-ext; 7 | 8 | interface fibo { 9 | use obelisk:types/execution@4.0.0.{execution-id}; 10 | use obelisk:types/join-set@4.0.0.{join-set}; 11 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 12 | 13 | fibo-submit: func(join-set: borrow, n: u8) -> execution-id; 14 | 15 | fibo-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 16 | 17 | fibo-get: func(execution-id: execution-id) -> result, get-extension-error>; 18 | } 19 | 20 | 21 | 22 | testing:fibo-obelisk-schedule 23 | package testing:fibo-obelisk-schedule; 24 | 25 | interface fibo { 26 | use obelisk:types/execution@4.0.0.{execution-id}; 27 | use obelisk:types/time@4.0.0.{schedule-at}; 28 | 29 | fibo-schedule: func(schedule-at: schedule-at, n: u8) -> execution-id; 30 | } 31 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/workflow/wasi/random.rs: -------------------------------------------------------------------------------- 1 | use super::wasi::{self, random::random}; 2 | use crate::workflow::workflow_ctx::WorkflowCtx; 3 | use concepts::time::ClockFn; 4 | 5 | impl random::Host for WorkflowCtx { 6 | fn get_random_bytes(&mut self, len: u64) -> wasmtime::Result> { 7 | let vec = vec![0; usize::try_from(len).unwrap()]; 8 | Ok(vec) 9 | } 10 | fn get_random_u64(&mut self) -> wasmtime::Result { 11 | Ok(0) 12 | } 13 | } 14 | 15 | impl wasi::random::insecure::Host for WorkflowCtx { 16 | fn get_insecure_random_bytes( 17 | &mut self, 18 | len: u64, 19 | ) -> wasmtime::Result> { 20 | Ok(std::iter::repeat_n(0, usize::try_from(len)?).collect()) 21 | } 22 | 23 | fn get_insecure_random_u64(&mut self) -> wasmtime::Result { 24 | Ok(0) 25 | } 26 | } 27 | impl wasi::random::insecure_seed::Host for WorkflowCtx { 28 | fn insecure_seed(&mut self) -> wasmtime::Result<(u64, u64)> { 29 | Ok((0, 0)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/grpc/build.rs: -------------------------------------------------------------------------------- 1 | use std::path::PathBuf; 2 | 3 | fn main() { 4 | let obelisk_proto = "proto/obelisk.proto"; 5 | println!("cargo:rerun-if-changed={obelisk_proto}"); 6 | let descriptor_path = 7 | PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR environment variable must be set")) 8 | .join("descriptor.bin"); 9 | tonic_prost_build::configure() 10 | .protoc_arg("--experimental_allow_proto3_optional") // not needed anymore with protoc 25.3 11 | .compile_well_known_types(true) 12 | .extern_path(".google.protobuf.Timestamp", "::prost_wkt_types::Timestamp") 13 | .extern_path(".google.protobuf.Duration", "::prost_wkt_types::Duration") 14 | .extern_path(".google.protobuf.Any", "::prost_wkt_types::Any") 15 | .type_attribute(".", "#[derive(serde::Serialize)]") // for CLI only 16 | .type_attribute(".", "#[serde(rename_all=\"snake_case\")]") // for CLI only 17 | .build_server(true) 18 | .build_client(true) 19 | .file_descriptor_set_path(descriptor_path) 20 | .compile_protos(&[obelisk_proto], &[]) 21 | .unwrap(); 22 | } 23 | -------------------------------------------------------------------------------- /crates/db-sqlite/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-db-sqlite" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | concepts = { workspace = true, features = ["rusqlite"] } 14 | val-json.workspace = true 15 | 16 | arbitrary.workspace = true 17 | assert_matches.workspace = true 18 | async-trait.workspace = true 19 | chrono.workspace = true 20 | const_format.workspace = true 21 | derive_more.workspace = true 22 | hashbrown.workspace = true 23 | hdrhistogram.workspace = true 24 | itertools.workspace = true 25 | rand.workspace = true 26 | rusqlite.workspace = true 27 | serde_json.workspace = true 28 | serde.workspace = true 29 | tempfile = { workspace = true, optional = true } 30 | thiserror.workspace = true 31 | tokio.workspace = true 32 | tracing.workspace = true 33 | 34 | [dev-dependencies] 35 | tempfile.workspace = true 36 | 37 | [features] 38 | tempfile = ["dep:tempfile"] 39 | test = [] 40 | 41 | [lints] 42 | workspace = true 43 | -------------------------------------------------------------------------------- /proto/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 obeli-sk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /toml/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 obeli-sk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /wit/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 obeli-sk 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /crates/executor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-executor" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | concepts.workspace = true 14 | utils.workspace = true 15 | val-json.workspace = true 16 | 17 | arbitrary.workspace = true 18 | assert_matches.workspace = true 19 | async-trait.workspace = true 20 | chrono.workspace = true 21 | derive_more.workspace = true 22 | hashbrown.workspace = true 23 | indexmap.workspace = true 24 | opentelemetry.workspace = true 25 | serde.workspace = true 26 | thiserror.workspace = true 27 | tokio.workspace = true 28 | tracing-opentelemetry.workspace = true 29 | tracing.workspace = true 30 | ulid.workspace = true 31 | 32 | [dev-dependencies] 33 | db-mem.workspace = true 34 | db-sqlite = { workspace = true, features = ["tempfile"] } 35 | test-utils.workspace = true 36 | db-tests.workspace = true 37 | 38 | anyhow.workspace = true 39 | rstest.workspace = true 40 | 41 | [features] 42 | test = [] 43 | 44 | [lints] 45 | workspace = true 46 | -------------------------------------------------------------------------------- /.github/workflows/check-extensions.yml: -------------------------------------------------------------------------------- 1 | name: check-extensions 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - latest 8 | pull_request: 9 | 10 | # If new code is pushed to a PR branch, then cancel in progress workflows for that PR. 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | defaults: 16 | run: 17 | shell: bash -xe {0} 18 | 19 | jobs: 20 | check-build-verify-toml-schema: 21 | runs-on: ubuntu-24.04 22 | steps: 23 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 24 | 25 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 26 | with: 27 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 28 | 29 | - name: Populate the nix store 30 | run: nix develop --command echo 31 | 32 | - name: Run `obelisk generate config-schema` 33 | run: | 34 | nix develop --command scripts/regenerate-wit-extensions.sh 35 | if [ -n "$(git status --porcelain)" ]; then 36 | echo "::error::Uncommitted changes after running 'regenerate-wit-extensions.sh'" 37 | exit 1 38 | fi 39 | -------------------------------------------------------------------------------- /crates/grpc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-grpc" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | concepts.workspace = true 14 | 15 | http.workspace = true 16 | prost-wkt-types.workspace = true 17 | prost.workspace = true 18 | serde_json.workspace = true 19 | serde.workspace = true 20 | thiserror.workspace = true 21 | tonic = { workspace = true, default-features = true, features = [ 22 | "zstd", 23 | "gzip", 24 | "tls-native-roots", 25 | ] } 26 | tonic-prost.workspace = true 27 | tracing.workspace = true 28 | 29 | # Optional deps: 30 | # otlp 31 | opentelemetry = { workspace = true, optional = true } 32 | tracing-opentelemetry = { workspace = true, optional = true } 33 | opentelemetry-http = { workspace = true, optional = true } 34 | [features] 35 | otlp = [ 36 | "dep:opentelemetry", 37 | "dep:tracing-opentelemetry", 38 | "dep:opentelemetry-http", 39 | ] 40 | default = ["otlp"] 41 | 42 | [build-dependencies] 43 | tonic-prost-build.workspace = true 44 | 45 | [lints] 46 | workspace = true 47 | -------------------------------------------------------------------------------- /.github/workflows/check-toml-schema.yml: -------------------------------------------------------------------------------- 1 | name: check-toml-schema 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - latest 8 | pull_request: 9 | 10 | # If new code is pushed to a PR branch, then cancel in progress workflows for that PR. 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 13 | cancel-in-progress: true 14 | 15 | 16 | defaults: 17 | run: 18 | shell: bash -xe {0} 19 | 20 | jobs: 21 | check-build-verify-toml-schema: 22 | runs-on: ubuntu-24.04 23 | steps: 24 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 25 | 26 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 27 | with: 28 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 29 | 30 | - name: Populate the nix store 31 | run: nix develop --command echo 32 | 33 | - name: Run `obelisk generate config-schema` 34 | run: | 35 | nix develop --command scripts/update-toml-schema.sh 36 | if [ -n "$(git status --porcelain)" ]; then 37 | echo "::error::Uncommitted changes after running 'obelisk generate config-schema toml/schema.json'" 38 | exit 1 39 | fi 40 | -------------------------------------------------------------------------------- /crates/utils/src/panic_hook.rs: -------------------------------------------------------------------------------- 1 | pub fn tracing_panic_hook(panic_info: &std::panic::PanicHookInfo) { 2 | let payload = panic_info.payload(); 3 | #[expect(clippy::manual_map)] 4 | let payload = if let Some(s) = payload.downcast_ref::<&str>() { 5 | Some(&**s) 6 | } else if let Some(s) = payload.downcast_ref::() { 7 | Some(s.as_str()) 8 | } else { 9 | None 10 | } 11 | .unwrap_or_default(); 12 | let location = panic_info.location().map(ToString::to_string); 13 | let backtrace = std::backtrace::Backtrace::capture(); 14 | if backtrace.status() == std::backtrace::BacktraceStatus::Captured { 15 | if tracing::enabled!(tracing::Level::ERROR) { 16 | tracing::error!( 17 | panic.location = location, 18 | "A panic occurred: `{payload}` {backtrace}" 19 | ); 20 | } else { 21 | eprintln!("A panic occurred: `{payload}`\n{backtrace}"); 22 | } 23 | } else if tracing::enabled!(tracing::Level::ERROR) { 24 | tracing::error!(panic.location = location, "A panic occurred: `{payload}`",); 25 | } else { 26 | eprintln!("A panic occurred: `{payload}`"); 27 | eprintln!("A panic occurred"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scripts/regenerate-wit-extensions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -exuo pipefail 4 | cd "$(dirname "$0")/.." 5 | 6 | cargo build 7 | CARGO_WORKSPACE_DIR=$(pwd) 8 | 9 | ( 10 | cd crates/testing/test-programs/fibo/activity/wit 11 | if [ "${RECREATE:-}" = "true" ]; then rm -rf gen; fi 12 | $CARGO_WORKSPACE_DIR/target/debug/obelisk generate extensions "$@" activity_wasm . gen 13 | ) 14 | ( 15 | cd crates/testing/test-programs/fibo/workflow/wit 16 | if [ "${RECREATE:-}" = "true" ]; then rm -rf gen; fi 17 | $CARGO_WORKSPACE_DIR/target/debug/obelisk generate extensions "$@" workflow . gen 18 | ) 19 | ( 20 | cd crates/testing/test-programs/http/activity/wit 21 | if [ "${RECREATE:-}" = "true" ]; then rm -rf gen; fi 22 | $CARGO_WORKSPACE_DIR/target/debug/obelisk generate extensions "$@" activity_wasm . gen 23 | ) 24 | ( 25 | cd crates/testing/test-programs/sleep/activity/wit 26 | if [ "${RECREATE:-}" = "true" ]; then rm -rf gen; fi 27 | $CARGO_WORKSPACE_DIR/target/debug/obelisk generate extensions "$@" activity_wasm . gen 28 | ) 29 | ( 30 | cd crates/testing/test-programs/stub/activity/wit 31 | if [ "${RECREATE:-}" = "true" ]; then rm -rf gen; fi 32 | $CARGO_WORKSPACE_DIR/target/debug/obelisk generate extensions "$@" activity_stub . gen 33 | ) 34 | -------------------------------------------------------------------------------- /wit/wasi_random@0.2.3/insecure-seed.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.3; 2 | /// The insecure-seed interface for seeding hash-map DoS resistance. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface insecure-seed { 8 | /// Return a 128-bit value that may contain a pseudo-random value. 9 | /// 10 | /// The returned value is not required to be computed from a CSPRNG, and may 11 | /// even be entirely deterministic. Host implementations are encouraged to 12 | /// provide pseudo-random values to any program exposed to 13 | /// attacker-controlled content, to enable DoS protection built into many 14 | /// languages' hash-map implementations. 15 | /// 16 | /// This function is intended to only be called once, by a source language 17 | /// to initialize Denial Of Service (DoS) protection in its hash-map 18 | /// implementation. 19 | /// 20 | /// # Expected future evolution 21 | /// 22 | /// This will likely be changed to a value import, to prevent it from being 23 | /// called multiple times and potentially used for purposes other than DoS 24 | /// protection. 25 | @since(version = 0.2.0) 26 | insecure-seed: func() -> tuple; 27 | } 28 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/epoch_ticker.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | sync::{Arc, atomic::AtomicBool}, 3 | time::Duration, 4 | }; 5 | use tracing::{debug, info}; 6 | use wasmtime::EngineWeak; 7 | 8 | pub struct EpochTicker { 9 | shutdown: Arc, 10 | } 11 | 12 | impl EpochTicker { 13 | #[must_use] 14 | pub fn spawn_new(engines: Vec, epoch: Duration) -> Self { 15 | info!("Spawning the epoch ticker"); 16 | let shutdown = Arc::new(AtomicBool::new(false)); 17 | std::thread::spawn({ 18 | let shutdown = shutdown.clone(); 19 | move || { 20 | while !shutdown.load(std::sync::atomic::Ordering::Relaxed) { 21 | std::thread::sleep(epoch); 22 | for engine in &engines { 23 | if let Some(engine) = engine.upgrade() { 24 | engine.increment_epoch(); 25 | } 26 | } 27 | } 28 | } 29 | }); 30 | Self { shutdown } 31 | } 32 | } 33 | 34 | impl Drop for EpochTicker { 35 | fn drop(&mut self) { 36 | debug!("Closing the epoch ticker"); 37 | self.shutdown 38 | .store(true, std::sync::atomic::Ordering::Relaxed); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /wit/wasi_random@0.2.3/random.wit: -------------------------------------------------------------------------------- 1 | package wasi:random@0.2.3; 2 | /// WASI Random is a random data API. 3 | /// 4 | /// It is intended to be portable at least between Unix-family platforms and 5 | /// Windows. 6 | @since(version = 0.2.0) 7 | interface random { 8 | /// Return `len` cryptographically-secure random or pseudo-random bytes. 9 | /// 10 | /// This function must produce data at least as cryptographically secure and 11 | /// fast as an adequately seeded cryptographically-secure pseudo-random 12 | /// number generator (CSPRNG). It must not block, from the perspective of 13 | /// the calling program, under any circumstances, including on the first 14 | /// request and on requests for numbers of bytes. The returned data must 15 | /// always be unpredictable. 16 | /// 17 | /// This function must always return fresh data. Deterministic environments 18 | /// must omit this function, rather than implementing it with deterministic 19 | /// data. 20 | @since(version = 0.2.0) 21 | get-random-bytes: func(len: u64) -> list; 22 | 23 | /// Return a cryptographically-secure random or pseudo-random `u64` value. 24 | /// 25 | /// This function returns the same type of data as `get-random-bytes`, 26 | /// represented as a `u64`. 27 | @since(version = 0.2.0) 28 | get-random-u64: func() -> u64; 29 | } 30 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::sleep::sleep::Guest; 2 | use obelisk::types::time::Duration as DurationEnum; 3 | use std::time::Duration; 4 | use wit_bindgen::generate; 5 | 6 | generate!({ generate_all }); 7 | struct Component; 8 | export!(Component); 9 | 10 | impl Guest for Component { 11 | fn sleep(duration: DurationEnum) -> Result<(), ()> { 12 | std::thread::sleep(Duration::from(duration)); 13 | Ok(()) 14 | } 15 | 16 | fn sleep_loop(duration: DurationEnum, iterations: u32) -> Result<(), ()> { 17 | for _ in 0..iterations { 18 | Self::sleep(duration).unwrap(); 19 | } 20 | Ok(()) 21 | } 22 | 23 | fn noop() -> Result<(), ()> { 24 | Ok(()) 25 | } 26 | } 27 | 28 | impl From for Duration { 29 | fn from(value: DurationEnum) -> Self { 30 | match value { 31 | DurationEnum::Milliseconds(millis) => Duration::from_millis(millis), 32 | DurationEnum::Seconds(secs) => Duration::from_secs(secs), 33 | DurationEnum::Minutes(mins) => Duration::from_secs(u64::from(mins * 60)), 34 | DurationEnum::Hours(hours) => Duration::from_secs(u64::from(hours * 60 * 60)), 35 | DurationEnum::Days(days) => Duration::from_secs(u64::from(days * 24 * 60 * 60)), 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /crates/concepts/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-concepts" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | val-json = { workspace = true, features = ["wasmtime"] } 14 | 15 | arbitrary.workspace = true 16 | assert_matches.workspace = true 17 | async-trait.workspace = true 18 | cfg-if.workspace = true 19 | chrono.workspace = true 20 | const_format.workspace = true 21 | derive-where.workspace = true 22 | derive_more.workspace = true 23 | fxhash.workspace = true 24 | hashbrown.workspace = true 25 | indexmap.workspace = true 26 | opentelemetry.workspace = true 27 | rand.workspace = true 28 | rusqlite = { optional = true, workspace = true } 29 | serde.workspace = true 30 | serde_json.workspace = true 31 | serde_with.workspace = true 32 | strum.workspace = true 33 | thiserror.workspace = true 34 | tokio.workspace = true 35 | tracing-opentelemetry.workspace = true 36 | tracing.workspace = true 37 | ulid.workspace = true 38 | wasmtime.workspace = true 39 | wasmtime-environ.workspace = true 40 | 41 | [dev-dependencies] 42 | insta.workspace = true 43 | rstest.workspace = true 44 | 45 | [features] 46 | test = [] 47 | rusqlite = ["dep:rusqlite"] 48 | 49 | [lints] 50 | workspace = true 51 | -------------------------------------------------------------------------------- /src/config/env_var.rs: -------------------------------------------------------------------------------- 1 | use schemars::JsonSchema; 2 | use serde::{Deserialize, Deserializer}; 3 | 4 | #[derive(Clone, derive_more::Debug, Hash, JsonSchema)] 5 | pub struct EnvVarConfig { 6 | pub key: String, 7 | #[debug(skip)] 8 | pub val: Option, 9 | } 10 | 11 | struct EnvVarConfigVisitor; 12 | 13 | impl serde::de::Visitor<'_> for EnvVarConfigVisitor { 14 | type Value = EnvVarConfig; 15 | 16 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 17 | formatter 18 | .write_str("either key of environment varaible to be forwarded from host, or key=value") 19 | } 20 | 21 | fn visit_str(self, input: &str) -> Result 22 | where 23 | E: serde::de::Error, 24 | { 25 | Ok(match input.split_once('=') { 26 | None => EnvVarConfig { 27 | key: input.to_string(), 28 | val: None, 29 | }, 30 | Some((k, input)) => EnvVarConfig { 31 | key: k.to_string(), 32 | val: Some(input.to_string()), 33 | }, 34 | }) 35 | } 36 | } 37 | impl<'de> Deserialize<'de> for EnvVarConfig { 38 | fn deserialize(deserializer: D) -> Result 39 | where 40 | D: Deserializer<'de>, 41 | { 42 | deserializer.deserialize_str(EnvVarConfigVisitor) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /crates/testing/test-programs/sleep/activity/wit/gen/testing_sleep-obelisk-ext/sleep-obelisk-ext.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.31.0-dev 2 | package testing:sleep-obelisk-ext; 3 | 4 | interface sleep { 5 | use obelisk:types/time@4.0.0.{duration}; 6 | use obelisk:types/execution@4.0.0.{execution-id}; 7 | use obelisk:types/join-set@4.0.0.{join-set}; 8 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 9 | 10 | sleep-submit: func(join-set: borrow, duration: duration) -> execution-id; 11 | 12 | sleep-await-next: func(join-set: borrow) -> result, await-next-extension-error>; 13 | 14 | sleep-get: func(execution-id: execution-id) -> result; 15 | 16 | sleep-loop-submit: func(join-set: borrow, duration: duration, iterations: u32) -> execution-id; 17 | 18 | sleep-loop-await-next: func(join-set: borrow) -> result, await-next-extension-error>; 19 | 20 | sleep-loop-get: func(execution-id: execution-id) -> result; 21 | 22 | noop-submit: func(join-set: borrow) -> execution-id; 23 | 24 | noop-await-next: func(join-set: borrow) -> result, await-next-extension-error>; 25 | 26 | noop-get: func(execution-id: execution-id) -> result; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/component_logger.rs: -------------------------------------------------------------------------------- 1 | use tracing::{Span, debug, error, info, trace, warn}; 2 | 3 | pub(crate) struct ComponentLogger { 4 | pub(crate) span: Span, 5 | // TODO: dynamic level filtering 6 | } 7 | const TARGET: &str = "app"; 8 | impl ComponentLogger { 9 | pub(crate) fn trace(&self, message: &str) { 10 | self.span.in_scope(|| trace!(target: TARGET, "{}", message)); 11 | } 12 | 13 | pub(crate) fn debug(&self, message: &str) { 14 | self.span.in_scope(|| debug!(target: TARGET, "{}", message)); 15 | } 16 | 17 | pub(crate) fn info(&self, message: &str) { 18 | self.span.in_scope(|| info!(target: TARGET, "{}", message)); 19 | } 20 | 21 | pub(crate) fn warn(&self, message: &str) { 22 | self.span.in_scope(|| warn!(target: TARGET, "{}", message)); 23 | } 24 | 25 | pub(crate) fn error(&self, message: &str) { 26 | self.span.in_scope(|| error!(target: TARGET, "{}", message)); 27 | } 28 | } 29 | 30 | pub(crate) mod log_activities { 31 | 32 | // Generate `obelisk::log::log` 33 | wasmtime::component::bindgen!({ 34 | path: "host-wit-log/", 35 | // interfaces: "import obelisk:log@1.0.0/log;", // Broken in 26.0.0 36 | inline: "package any:any; 37 | world bindings { 38 | import obelisk:log/log@1.0.0; 39 | }", 40 | world: "any:any/bindings", 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/wit/gen/testing_fibo-workflow-obelisk-ext/fibo-workflow-obelisk-ext.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.31.0-dev 2 | package testing:fibo-workflow-obelisk-ext; 3 | 4 | interface workflow { 5 | use obelisk:types/execution@4.0.0.{execution-id}; 6 | use obelisk:types/join-set@4.0.0.{join-set}; 7 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 8 | 9 | fibow-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 10 | 11 | fibow-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 12 | 13 | fibow-get: func(execution-id: execution-id) -> result, get-extension-error>; 14 | 15 | fiboa-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 16 | 17 | fiboa-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 18 | 19 | fiboa-get: func(execution-id: execution-id) -> result, get-extension-error>; 20 | 21 | fiboa-concurrent-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 22 | 23 | fiboa-concurrent-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 24 | 25 | fiboa-concurrent-get: func(execution-id: execution-id) -> result, get-extension-error>; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /crates/wasm-workers/src/workflow/wasi/clocks.rs: -------------------------------------------------------------------------------- 1 | use super::wasi::clocks::{monotonic_clock, wall_clock}; 2 | use crate::workflow::workflow_ctx::WorkflowCtx; 3 | use concepts::time::ClockFn; 4 | use wasmtime::component::Resource; 5 | use wasmtime_wasi_io::poll::DynPollable; 6 | 7 | impl monotonic_clock::Host for WorkflowCtx { 8 | fn now(&mut self) -> wasmtime::Result { 9 | Ok(monotonic_clock::Instant::MIN) 10 | } 11 | fn resolution(&mut self) -> wasmtime::Result { 12 | Err(wasmtime::Error::msg("wasi:clocks is stubbed")) 13 | } 14 | fn subscribe_duration( 15 | &mut self, 16 | _duration: monotonic_clock::Duration, 17 | ) -> wasmtime::Result> { 18 | Err(wasmtime::Error::msg("wasi:clocks is stubbed")) 19 | } 20 | fn subscribe_instant( 21 | &mut self, 22 | _deadline: monotonic_clock::Instant, 23 | ) -> wasmtime::Result> { 24 | Err(wasmtime::Error::msg("wasi:clocks is stubbed")) 25 | } 26 | } 27 | 28 | impl wall_clock::Host for WorkflowCtx { 29 | fn now(&mut self) -> wasmtime::Result { 30 | Ok(wall_clock::Datetime { 31 | seconds: 0, 32 | nanoseconds: 0, 33 | }) 34 | } 35 | 36 | fn resolution(&mut self) -> wasmtime::Result { 37 | Err(wasmtime::Error::msg("wasi:clocks is stubbed")) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@stub__activity.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: snapshot 4 | --- 5 | testing:stub-activity-obelisk-ext 6 | package testing:stub-activity-obelisk-ext; 7 | 8 | interface activity { 9 | use obelisk:types/execution@4.0.0.{execution-id}; 10 | use obelisk:types/join-set@4.0.0.{join-set}; 11 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 12 | 13 | foo-submit: func(join-set: borrow, arg: string) -> execution-id; 14 | 15 | foo-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 16 | 17 | foo-get: func(execution-id: execution-id) -> result, get-extension-error>; 18 | 19 | noret-submit: func(join-set: borrow) -> execution-id; 20 | 21 | noret-await-next: func(join-set: borrow) -> result, await-next-extension-error>; 22 | 23 | noret-get: func(execution-id: execution-id) -> result; 24 | } 25 | 26 | 27 | 28 | testing:stub-activity-obelisk-stub 29 | package testing:stub-activity-obelisk-stub; 30 | 31 | interface activity { 32 | use obelisk:types/execution@4.0.0.{execution-id, stub-error}; 33 | 34 | foo-stub: func(execution-id: execution-id, execution-result: result) -> result<_, stub-error>; 35 | 36 | noret-stub: func(execution-id: execution-id, execution-result: result) -> result<_, stub-error>; 37 | } 38 | -------------------------------------------------------------------------------- /crates/testing/test-programs/dir/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::dir::dir::Guest; 2 | use std::path::PathBuf; 3 | use wit_bindgen::generate; 4 | 5 | generate!({ generate_all }); 6 | struct Component; 7 | export!(Component); 8 | 9 | impl Guest for Component { 10 | fn io() -> Result<(), String> { 11 | let entries = ls(); 12 | // Let's put some content idempotently 13 | let tempfile = PathBuf::from("test.txt"); 14 | std::fs::write(tempfile, b"Lorem ipsum").expect("writing to a file failed"); 15 | std::fs::create_dir_all("foo/bar/baz").expect("create_dir_all failed"); 16 | 17 | if entries.is_empty() { 18 | // Should be retried and succeed.. 19 | return Err( 20 | "failing on first try, should be automatically fixed on the first retry if `reuse_on_retry` is enabled" 21 | .to_string(), 22 | ); 23 | } 24 | 25 | let entries = ls(); 26 | if entries != vec!["./foo", "./test.txt"] { 27 | return Err(format!("unexpected file list: {entries:?}")); 28 | } 29 | 30 | Ok(()) 31 | } 32 | } 33 | 34 | fn ls() -> Vec { 35 | let mut entries = std::fs::read_dir(".") 36 | .expect("read_dir failed") 37 | .map(|res| res.map(|e| e.path().to_string_lossy().into_owned())) 38 | .collect::, _>>() 39 | .expect("iterating over folder failed"); 40 | entries.sort(); 41 | println!("ls:"); 42 | println!("{entries:?}"); 43 | entries 44 | } 45 | -------------------------------------------------------------------------------- /scripts/dev-deps.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Collect versions of binaries installed by `nix develop` producing file `dev-deps.txt`. 4 | # This script should be executed after every `nix flake update`. 5 | 6 | set -exuo pipefail 7 | cd "$(dirname "$0")/.." 8 | 9 | 10 | get_litestream_version() { 11 | WORKSPACE_DIR="$(pwd -P)" 12 | TMP_DIR=$(mktemp -d) 13 | ( 14 | cd "$TMP_DIR" || exit 1 15 | touch obelisk obelisk.toml 16 | 17 | docker build -f "$WORKSPACE_DIR/.github/workflows/release/docker-image/ubuntu-24.04-litestream.Dockerfile" . --tag temp >/dev/null 18 | docker run --rm --entrypoint litestream temp version 19 | docker rmi temp >/dev/null 20 | ) 21 | rm -rf "$TMP_DIR" 22 | } 23 | 24 | rm -f dev-deps.txt 25 | echo "cargo-binstall $(cargo-binstall -V)" >> dev-deps.txt 26 | cargo upgrade --version >> dev-deps.txt 27 | cargo-expand --version >> dev-deps.txt 28 | cargo-insta --version >> dev-deps.txt 29 | cargo nextest --version | head -n 1 >> dev-deps.txt 30 | cargo semver-checks --version >> dev-deps.txt 31 | echo "litecli $(litecli --version)" >> dev-deps.txt 32 | echo $(nixpkgs-fmt --version) >> dev-deps.txt 33 | echo "pkg-config $(pkg-config --version)" >> dev-deps.txt 34 | # protobuf 35 | protoc --version >> dev-deps.txt 36 | rustc --version >> dev-deps.txt 37 | wasm-tools --version >> dev-deps.txt 38 | wasmtime --version >> dev-deps.txt 39 | cargo-zigbuild --version >> dev-deps.txt 40 | 41 | # docker deps 42 | echo "litestream $(get_litestream_version)" >> dev-deps.txt 43 | 44 | # libc 45 | ldd --version | head -n 1 >> dev-deps.txt 46 | 47 | 48 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate::exports::testing::http::http_get::Guest; 2 | use exports::testing::http::http_get; 3 | use std::time::Duration; 4 | use wit_bindgen::generate; 5 | 6 | generate!({ generate_all }); 7 | struct Component; 8 | export!(Component); 9 | 10 | impl Guest for Component { 11 | fn get(url: String) -> Result { 12 | let resp = Self::get_resp(url)?; 13 | Ok(String::from_utf8_lossy(&resp.body).into_owned()) 14 | } 15 | 16 | fn get_successful(url: String) -> Result { 17 | let resp = Self::get_resp(url)?; 18 | if resp.status_code >= 200 && resp.status_code <= 299 { 19 | Ok(String::from_utf8_lossy(&resp.body).into_owned()) 20 | } else { 21 | assert!(resp.status_code != 418, "418 causes trap"); 22 | Err(format!("wrong status code: {}", resp.status_code)) 23 | } 24 | } 25 | 26 | fn get_resp(url: String) -> Result { 27 | let resp = waki::Client::new() 28 | .get(&url) 29 | .connect_timeout(Duration::from_secs(1)) 30 | .send() 31 | .map_err(|err| format!("{err:?}"))?; 32 | let status_code = resp.status_code(); 33 | let body = resp.body().map_err(|err| format!("{err:?}"))?; 34 | Ok(http_get::Response { body, status_code }) 35 | } 36 | 37 | fn get_stargazers() -> Result { 38 | Ok(http_get::Stargazers { 39 | cursor: "cursor".to_string(), 40 | logins: "logins".to_string(), 41 | }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /wit/wasi_io@0.2.3/error.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.3; 2 | 3 | @since(version = 0.2.0) 4 | interface error { 5 | /// A resource which represents some error information. 6 | /// 7 | /// The only method provided by this resource is `to-debug-string`, 8 | /// which provides some human-readable information about the error. 9 | /// 10 | /// In the `wasi:io` package, this resource is returned through the 11 | /// `wasi:io/streams/stream-error` type. 12 | /// 13 | /// To provide more specific error information, other interfaces may 14 | /// offer functions to "downcast" this error into more specific types. For example, 15 | /// errors returned from streams derived from filesystem types can be described using 16 | /// the filesystem's own error-code type. This is done using the function 17 | /// `wasi:filesystem/types/filesystem-error-code`, which takes a `borrow` 18 | /// parameter and returns an `option`. 19 | /// 20 | /// The set of functions which can "downcast" an `error` into a more 21 | /// concrete type is open. 22 | @since(version = 0.2.0) 23 | resource error { 24 | /// Returns a string that is suitable to assist humans in debugging 25 | /// this error. 26 | /// 27 | /// WARNING: The returned string should not be consumed mechanically! 28 | /// It may change across platforms, hosts, or other implementation 29 | /// details. Parsing this string is a major platform-compatibility 30 | /// hazard. 31 | @since(version = 0.2.0) 32 | to-debug-string: func() -> string; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::fibo_workflow::workflow::Guest; 2 | use obelisk::workflow::workflow_support::join_set_create; 3 | use testing::{ 4 | fibo::fibo::fibo as fibo_activity, 5 | fibo_obelisk_ext::fibo::{fibo_await_next, fibo_submit}, 6 | }; 7 | use wit_bindgen::generate; 8 | 9 | generate!({ generate_all }); 10 | struct Component; 11 | export!(Component); 12 | 13 | pub fn black_box(dummy: T) -> T { 14 | unsafe { 15 | let ret = std::ptr::read_volatile(&raw const dummy); 16 | std::mem::forget(dummy); 17 | ret 18 | } 19 | } 20 | 21 | impl Guest for Component { 22 | fn fibow(n: u8, iterations: u32) -> Result { 23 | let mut last = 0; 24 | for _ in 0..iterations { 25 | last = fibo(black_box(n)); 26 | } 27 | Ok(last) 28 | } 29 | 30 | fn fiboa(n: u8, iterations: u32) -> Result { 31 | let mut last = 0; 32 | for _ in 0..iterations { 33 | last = fibo_activity(n).unwrap(); 34 | } 35 | Ok(last) 36 | } 37 | 38 | fn fiboa_concurrent(n: u8, iterations: u32) -> Result { 39 | let join_set = join_set_create(); 40 | for _ in 0..iterations { 41 | fibo_submit(&join_set, n); 42 | } 43 | let mut last = 0; 44 | for _ in 0..iterations { 45 | last = fibo_await_next(&join_set).unwrap().1.unwrap(); 46 | } 47 | Ok(last) 48 | } 49 | } 50 | 51 | #[must_use] 52 | pub fn fibo(n: u8) -> u64 { 53 | if n == 0 { 54 | 0 55 | } else if n == 1 { 56 | 1 57 | } else { 58 | fibo(n - 1) + fibo(n - 2) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /wit/wasi_sockets@0.2.3/udp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface udp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use udp.{udp-socket}; 7 | 8 | /// Create a new UDP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_DGRAM, IPPROTO_UDP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind` is called, 15 | /// the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References: 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-udp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /wit/wasi_sockets@0.2.3/tcp-create-socket.wit: -------------------------------------------------------------------------------- 1 | @since(version = 0.2.0) 2 | interface tcp-create-socket { 3 | @since(version = 0.2.0) 4 | use network.{network, error-code, ip-address-family}; 5 | @since(version = 0.2.0) 6 | use tcp.{tcp-socket}; 7 | 8 | /// Create a new TCP socket. 9 | /// 10 | /// Similar to `socket(AF_INET or AF_INET6, SOCK_STREAM, IPPROTO_TCP)` in POSIX. 11 | /// On IPv6 sockets, IPV6_V6ONLY is enabled by default and can't be configured otherwise. 12 | /// 13 | /// This function does not require a network capability handle. This is considered to be safe because 14 | /// at time of creation, the socket is not bound to any `network` yet. Up to the moment `bind`/`connect` 15 | /// is called, the socket is effectively an in-memory configuration object, unable to communicate with the outside world. 16 | /// 17 | /// All sockets are non-blocking. Use the wasi-poll interface to block on asynchronous operations. 18 | /// 19 | /// # Typical errors 20 | /// - `not-supported`: The specified `address-family` is not supported. (EAFNOSUPPORT) 21 | /// - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) 22 | /// 23 | /// # References 24 | /// - 25 | /// - 26 | /// - 27 | /// - 28 | @since(version = 0.2.0) 29 | create-tcp-socket: func(address-family: ip-address-family) -> result; 30 | } 31 | -------------------------------------------------------------------------------- /crates/utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-utils" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | concepts.workspace = true 14 | val-json = { workspace = true, features = ["wit-parser"] } 15 | 16 | anyhow.workspace = true 17 | async-trait.workspace = true 18 | chrono.workspace = true 19 | const_format.workspace = true 20 | derive_more.workspace = true 21 | hashbrown.workspace = true 22 | hyper.workspace = true 23 | id-arena.workspace = true 24 | indexmap.workspace = true 25 | semver.workspace = true 26 | sha2.workspace = true 27 | strum.workspace = true 28 | thiserror.workspace = true 29 | tokio.workspace = true 30 | tracing.workspace = true 31 | wasmparser.workspace = true 32 | wit-component.workspace = true 33 | wit-parser.workspace = true 34 | 35 | [dev-dependencies] 36 | concepts = { workspace = true, features = ["test"] } 37 | 38 | insta.workspace = true 39 | rstest.workspace = true 40 | serde.workspace = true 41 | test-programs-fibo-activity-builder.workspace = true 42 | test-programs-fibo-webhook-builder.workspace = true 43 | test-programs-fibo-workflow-builder.workspace = true 44 | test-programs-http-get-activity-builder.workspace = true 45 | test-programs-http-get-workflow-builder.workspace = true 46 | test-programs-sleep-activity-builder.workspace = true 47 | test-programs-sleep-workflow-builder.workspace = true 48 | test-programs-stub-activity-builder.workspace = true 49 | test-programs-stub-workflow-builder.workspace = true 50 | test-utils.workspace = true 51 | tokio.workspace = true 52 | 53 | [lints] 54 | workspace = true 55 | -------------------------------------------------------------------------------- /scripts/push-test-components.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Push all WASM components from crates/testing/test-programs to the Docker Hub and update obelisk-oci.toml 4 | 5 | set -exuo pipefail 6 | cd "$(dirname "$0")/.." 7 | 8 | TAG="$1" 9 | TOML_FILE="obelisk.toml" 10 | PREFIX="docker.io/getobelisk/" 11 | 12 | cargo check --workspace # starts build.rs of each -builder 13 | 14 | push() { 15 | RELATIVE_PATH=$1 16 | FILE_NAME_WITHOUT_EXT=$(basename "$RELATIVE_PATH" | sed 's/\.[^.]*$//') 17 | OCI_LOCATION="${PREFIX}${FILE_NAME_WITHOUT_EXT}:${TAG}" 18 | echo "Pushing ${RELATIVE_PATH} to ${OCI_LOCATION}..." 19 | OUTPUT=$(cargo run -- client component push "$RELATIVE_PATH" "$OCI_LOCATION") 20 | 21 | # Replace the old location with the actual OCI location 22 | sed -i -E "/name = \"${FILE_NAME_WITHOUT_EXT}\"/{n;s|location\.oci = \".*\"|location.oci = \"${OUTPUT}\"|}" "$TOML_FILE" 23 | } 24 | 25 | # Make sure all components are fresh 26 | cargo check --workspace 27 | 28 | push "target/release_testprograms/wasm32-wasip2/release_wasm/test_programs_fibo_activity.wasm" 29 | push "target/release_testprograms/wasm32-unknown-unknown/release_wasm/test_programs_fibo_workflow.wasm" 30 | push "target/release_testprograms/wasm32-wasip2/release_wasm/test_programs_fibo_webhook.wasm" 31 | push "target/release_testprograms/wasm32-wasip2/release_wasm/test_programs_http_get_activity.wasm" 32 | push "target/release_testprograms/wasm32-unknown-unknown/release_wasm/test_programs_http_get_workflow.wasm" 33 | push "target/release_testprograms/wasm32-wasip2/release_wasm/test_programs_sleep_activity.wasm" 34 | push "target/release_testprograms/wasm32-unknown-unknown/release_wasm/test_programs_sleep_workflow.wasm" 35 | 36 | echo "All components pushed and TOML file updated successfully." 37 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/webhook/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate::obelisk::log::log::info; 2 | use crate::obelisk::types::time::ScheduleAt; 3 | use crate::testing::fibo_workflow::workflow; 4 | use crate::testing::fibo_workflow_obelisk_schedule::workflow as workflow_schedule; 5 | use waki::{ErrorCode, Request, Response, handler}; 6 | use wit_bindgen::generate; 7 | 8 | generate!({ generate_all }); 9 | 10 | #[handler] 11 | fn handle(_req: Request) -> Result { 12 | let Ok(n) = std::env::var("N") 13 | .expect("env var `N` must be set by Obelisk if routes are configured properly") 14 | .parse() 15 | else { 16 | return Response::builder().status_code(400).build(); 17 | }; 18 | 19 | let Ok(iterations) = std::env::var("ITERATIONS") 20 | .expect("env var `ITERATIONS` must be set by Obelisk if routes are configured properly") 21 | .parse() 22 | else { 23 | return Response::builder().status_code(400).build(); 24 | }; 25 | 26 | let fibo_res = if n >= 10 { 27 | println!("scheduling"); 28 | let execution_id = workflow_schedule::fiboa_schedule(ScheduleAt::Now, n, iterations); 29 | format!("scheduled: {}", execution_id.id) 30 | } else if n > 1 { 31 | // Call the execution directly. 32 | println!("direct call"); 33 | let fibo_res = workflow::fiboa(n, iterations).unwrap(); 34 | format!("direct call: {fibo_res}") 35 | } else { 36 | assert_eq!(iterations, 0); // For testing traps 37 | println!("hardcoded"); 38 | "hardcoded: 1".to_string() // For performance testing - no activity is called 39 | }; 40 | info(&format!("Sending response {fibo_res}")); 41 | Response::builder() 42 | .body(format!("fiboa({n}, {iterations}) = {fibo_res}")) 43 | .build() 44 | } 45 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/activity/wit/gen/testing_http-obelisk-ext/http-obelisk-ext.wit: -------------------------------------------------------------------------------- 1 | // Generated by Obelisk 0.31.0-dev 2 | package testing:http-obelisk-ext; 3 | 4 | interface http-get { 5 | use testing:http/http-get.{response, stargazers}; 6 | use obelisk:types/execution@4.0.0.{execution-id}; 7 | use obelisk:types/join-set@4.0.0.{join-set}; 8 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 9 | 10 | get-submit: func(join-set: borrow, url: string) -> execution-id; 11 | 12 | get-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 13 | 14 | get-get: func(execution-id: execution-id) -> result, get-extension-error>; 15 | 16 | get-resp-submit: func(join-set: borrow, url: string) -> execution-id; 17 | 18 | get-resp-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 19 | 20 | get-resp-get: func(execution-id: execution-id) -> result, get-extension-error>; 21 | 22 | get-stargazers-submit: func(join-set: borrow) -> execution-id; 23 | 24 | get-stargazers-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 25 | 26 | get-stargazers-get: func(execution-id: execution-id) -> result, get-extension-error>; 27 | 28 | get-successful-submit: func(join-set: borrow, url: string) -> execution-id; 29 | 30 | get-successful-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 31 | 32 | get-successful-get: func(execution-id: execution-id) -> result, get-extension-error>; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /crates/testing/test-utils/src/sim_clock.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Utc}; 2 | use concepts::time::{ClockFn, Now}; 3 | use std::{sync::Arc, time::Duration}; 4 | use tracing::info; 5 | 6 | #[derive(Clone)] 7 | pub struct SimClock { 8 | current_time: Arc>>, 9 | } 10 | 11 | impl Default for SimClock { 12 | // TODO: Rename to system_time 13 | fn default() -> Self { 14 | Self::new(Now.now()) 15 | } 16 | } 17 | 18 | impl SimClock { 19 | #[must_use] 20 | pub fn epoch() -> SimClock { 21 | Self::new(DateTime::from_timestamp_nanos(0)) 22 | } 23 | } 24 | 25 | impl SimClock { 26 | #[must_use] 27 | pub fn new(now: DateTime) -> Self { 28 | Self { 29 | current_time: Arc::new(std::sync::Mutex::new(now)), 30 | } 31 | } 32 | 33 | pub fn move_time_forward(&self, duration: Duration) { 34 | let (old, new) = { 35 | let mut guard = self.current_time.lock().unwrap(); 36 | let old = *guard; 37 | let new = old + duration; 38 | *guard = new; 39 | (old, new) 40 | }; 41 | info!("Set clock from `{old}` to `{new}`"); 42 | } 43 | 44 | pub fn move_time_to(&self, new: DateTime) { 45 | let (old, new) = { 46 | let mut guard = self.current_time.lock().unwrap(); 47 | let old = *guard; 48 | assert!(old <= new); 49 | *guard = new; 50 | (old, new) 51 | }; 52 | info!("Set clock from `{old}` to `{new}`"); 53 | } 54 | } 55 | impl ClockFn for SimClock { 56 | fn now(&self) -> DateTime { 57 | *self.current_time.lock().unwrap() 58 | } 59 | } 60 | 61 | #[derive(Clone, Copy)] 62 | pub struct ConstClock(pub DateTime); 63 | impl ClockFn for ConstClock { 64 | fn now(&self) -> DateTime { 65 | self.0 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /wit/wasi_clocks@0.2.3/monotonic-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.3; 2 | /// WASI Monotonic Clock is a clock API intended to let users measure elapsed 3 | /// time. 4 | /// 5 | /// It is intended to be portable at least between Unix-family platforms and 6 | /// Windows. 7 | /// 8 | /// A monotonic clock is a clock which has an unspecified initial value, and 9 | /// successive reads of the clock will produce non-decreasing values. 10 | @since(version = 0.2.0) 11 | interface monotonic-clock { 12 | @since(version = 0.2.0) 13 | use wasi:io/poll@0.2.3.{pollable}; 14 | 15 | /// An instant in time, in nanoseconds. An instant is relative to an 16 | /// unspecified initial value, and can only be compared to instances from 17 | /// the same monotonic-clock. 18 | @since(version = 0.2.0) 19 | type instant = u64; 20 | 21 | /// A duration of time, in nanoseconds. 22 | @since(version = 0.2.0) 23 | type duration = u64; 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// The clock is monotonic, therefore calling this function repeatedly will 28 | /// produce a sequence of non-decreasing values. 29 | @since(version = 0.2.0) 30 | now: func() -> instant; 31 | 32 | /// Query the resolution of the clock. Returns the duration of time 33 | /// corresponding to a clock tick. 34 | @since(version = 0.2.0) 35 | resolution: func() -> duration; 36 | 37 | /// Create a `pollable` which will resolve once the specified instant 38 | /// has occurred. 39 | @since(version = 0.2.0) 40 | subscribe-instant: func( 41 | when: instant, 42 | ) -> pollable; 43 | 44 | /// Create a `pollable` that will resolve after the specified duration has 45 | /// elapsed from the time this function is invoked. 46 | @since(version = 0.2.0) 47 | subscribe-duration: func( 48 | when: duration, 49 | ) -> pollable; 50 | } 51 | -------------------------------------------------------------------------------- /download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Downloads the latest binary from GitHub Releases into the current directory. 4 | # Usage: 5 | # curl -L --tlsv1.2 -sSf https://raw.githubusercontent.com/obeli-sk/obelisk/main/download.sh | bash 6 | 7 | set -eu 8 | 9 | # Set pipefail if it works in a subshell, disregard if unsupported 10 | (set -o pipefail 2> /dev/null) && set -o pipefail 11 | 12 | base_url="https://github.com/obeli-sk/obelisk/releases/latest/download/obelisk-" 13 | 14 | os="$(uname -s)" 15 | if [ "$os" = "Linux" ]; then 16 | machine="$(uname -m)" 17 | case "$machine" in 18 | x86_64) target="x86_64-unknown-linux-" ;; 19 | aarch64) target="aarch64-unknown-linux-" ;; 20 | *) echo "Unsupported architecture ${machine}" && exit 1 ;; 21 | esac 22 | 23 | # Use musl on NixOS and musl-based systems. 24 | ldd_version=$(ldd --version 2>&1 || true) 25 | issue=$(cat /etc/issue 2>/dev/null || true) 26 | if echo "$ldd_version" | grep -q "musl" || echo "$issue" | grep -q "NixOS"; then 27 | lib="musl" 28 | if echo "$issue" | grep -q "NixOS"; then 29 | echo -e "Downloading musl-based bianry on NixOS. Consider installing with\nnix profile install github:obeli-sk/obelisk/latest" 30 | fi 31 | else 32 | lib="gnu" 33 | fi 34 | url="${base_url}${target}${lib}.tar.gz" 35 | 36 | elif [ "$os" = "Darwin" ]; then 37 | machine="$(uname -m)" 38 | case "$machine" in 39 | x86_64) target="x86_64-apple-darwin" ;; 40 | arm64) target="aarch64-apple-darwin" ;; 41 | *) echo "Unsupported architecture ${machine}" && exit 1 ;; 42 | esac 43 | 44 | url="${base_url}${target}.tar.gz" 45 | 46 | else 47 | echo "Unsupported OS ${os}" 48 | exit 1 49 | fi 50 | 51 | # Download and extract the tarball 52 | echo "Downloading and extracting $url" 53 | curl -L --proto '=https' --tlsv1.2 -sSf "$url" | tar -xvzf - 54 | -------------------------------------------------------------------------------- /wit/wasi_io@0.2.3/poll.wit: -------------------------------------------------------------------------------- 1 | package wasi:io@0.2.3; 2 | 3 | /// A poll API intended to let users wait for I/O events on multiple handles 4 | /// at once. 5 | @since(version = 0.2.0) 6 | interface poll { 7 | /// `pollable` represents a single I/O event which may be ready, or not. 8 | @since(version = 0.2.0) 9 | resource pollable { 10 | 11 | /// Return the readiness of a pollable. This function never blocks. 12 | /// 13 | /// Returns `true` when the pollable is ready, and `false` otherwise. 14 | @since(version = 0.2.0) 15 | ready: func() -> bool; 16 | 17 | /// `block` returns immediately if the pollable is ready, and otherwise 18 | /// blocks until ready. 19 | /// 20 | /// This function is equivalent to calling `poll.poll` on a list 21 | /// containing only this pollable. 22 | @since(version = 0.2.0) 23 | block: func(); 24 | } 25 | 26 | /// Poll for completion on a set of pollables. 27 | /// 28 | /// This function takes a list of pollables, which identify I/O sources of 29 | /// interest, and waits until one or more of the events is ready for I/O. 30 | /// 31 | /// The result `list` contains one or more indices of handles in the 32 | /// argument list that is ready for I/O. 33 | /// 34 | /// This function traps if either: 35 | /// - the list is empty, or: 36 | /// - the list contains more elements than can be indexed with a `u32` value. 37 | /// 38 | /// A timeout can be implemented by adding a pollable from the 39 | /// wasi-clocks API to the list. 40 | /// 41 | /// This function does not return a `result`; polling in itself does not 42 | /// do any I/O so it doesn't fail. If any of the I/O sources identified by 43 | /// the pollables has an error, it is indicated by marking the source as 44 | /// being ready for I/O. 45 | @since(version = 0.2.0) 46 | poll: func(in: list>) -> list; 47 | } 48 | -------------------------------------------------------------------------------- /wit/wasi_clocks@0.2.3/wall-clock.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.3; 2 | /// WASI Wall Clock is a clock API intended to let users query the current 3 | /// time. The name "wall" makes an analogy to a "clock on the wall", which 4 | /// is not necessarily monotonic as it may be reset. 5 | /// 6 | /// It is intended to be portable at least between Unix-family platforms and 7 | /// Windows. 8 | /// 9 | /// A wall clock is a clock which measures the date and time according to 10 | /// some external reference. 11 | /// 12 | /// External references may be reset, so this clock is not necessarily 13 | /// monotonic, making it unsuitable for measuring elapsed time. 14 | /// 15 | /// It is intended for reporting the current date and time for humans. 16 | @since(version = 0.2.0) 17 | interface wall-clock { 18 | /// A time and date in seconds plus nanoseconds. 19 | @since(version = 0.2.0) 20 | record datetime { 21 | seconds: u64, 22 | nanoseconds: u32, 23 | } 24 | 25 | /// Read the current value of the clock. 26 | /// 27 | /// This clock is not monotonic, therefore calling this function repeatedly 28 | /// will not necessarily produce a sequence of non-decreasing values. 29 | /// 30 | /// The returned timestamps represent the number of seconds since 31 | /// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch], 32 | /// also known as [Unix Time]. 33 | /// 34 | /// The nanoseconds field of the output is always less than 1000000000. 35 | /// 36 | /// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16 37 | /// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time 38 | @since(version = 0.2.0) 39 | now: func() -> datetime; 40 | 41 | /// Query the resolution of the clock. 42 | /// 43 | /// The nanoseconds field of the output is always less than 1000000000. 44 | @since(version = 0.2.0) 45 | resolution: func() -> datetime; 46 | } 47 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__wit_folder_parsing@fibo__workflow.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: snapshot 4 | --- 5 | testing:fibo-workflow-obelisk-ext 6 | package testing:fibo-workflow-obelisk-ext; 7 | 8 | interface workflow { 9 | use obelisk:types/execution@4.0.0.{execution-id}; 10 | use obelisk:types/join-set@4.0.0.{join-set}; 11 | use obelisk:types/execution@4.0.0.{await-next-extension-error, get-extension-error}; 12 | 13 | fibow-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 14 | 15 | fibow-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 16 | 17 | fibow-get: func(execution-id: execution-id) -> result, get-extension-error>; 18 | 19 | fiboa-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 20 | 21 | fiboa-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 22 | 23 | fiboa-get: func(execution-id: execution-id) -> result, get-extension-error>; 24 | 25 | fiboa-concurrent-submit: func(join-set: borrow, n: u8, iterations: u32) -> execution-id; 26 | 27 | fiboa-concurrent-await-next: func(join-set: borrow) -> result>, await-next-extension-error>; 28 | 29 | fiboa-concurrent-get: func(execution-id: execution-id) -> result, get-extension-error>; 30 | } 31 | 32 | 33 | 34 | testing:fibo-workflow-obelisk-schedule 35 | package testing:fibo-workflow-obelisk-schedule; 36 | 37 | interface workflow { 38 | use obelisk:types/execution@4.0.0.{execution-id}; 39 | use obelisk:types/time@4.0.0.{schedule-at}; 40 | 41 | fibow-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 42 | 43 | fiboa-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 44 | 45 | fiboa-concurrent-schedule: func(schedule-at: schedule-at, n: u8, iterations: u32) -> execution-id; 46 | } 47 | -------------------------------------------------------------------------------- /crates/testing/db-tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use concepts::FunctionFqn; 3 | use concepts::storage::DbExecutor; 4 | use concepts::storage::DbPool; 5 | use concepts::storage::DbPoolCloseable; 6 | use db_mem::inmemory_dao::InMemoryPool; 7 | use db_sqlite::sqlite_dao::SqlitePool; 8 | use std::sync::Arc; 9 | use tempfile::NamedTempFile; 10 | 11 | pub const SOME_FFQN: FunctionFqn = FunctionFqn::new_static("pkg/ifc", "fn"); 12 | 13 | #[derive(Clone, Copy, Debug)] 14 | pub enum Database { 15 | Memory, 16 | Sqlite, 17 | } 18 | 19 | pub enum DbGuard { 20 | Memory, 21 | Sqlite(Option), 22 | } 23 | 24 | impl Database { 25 | pub async fn set_up( 26 | self, 27 | ) -> ( 28 | DbGuard, 29 | Arc, 30 | Arc, 31 | DbPoolCloseableWrapper, 32 | ) { 33 | match self { 34 | Database::Memory => { 35 | let mem_db = InMemoryPool::new(); 36 | let exec = mem_db.db_executor(); 37 | let closeable = DbPoolCloseableWrapper::Memory(mem_db.clone()); 38 | (DbGuard::Memory, Arc::new(mem_db), exec, closeable) 39 | } 40 | Database::Sqlite => { 41 | use db_sqlite::sqlite_dao::tempfile::sqlite_pool; 42 | let (sqlite, guard) = sqlite_pool().await; 43 | let closeable = DbPoolCloseableWrapper::Sqlite(sqlite.clone()); 44 | ( 45 | DbGuard::Sqlite(guard), 46 | Arc::new(sqlite.clone()), 47 | Arc::new(sqlite), 48 | closeable, 49 | ) 50 | } 51 | } 52 | } 53 | } 54 | 55 | pub enum DbPoolCloseableWrapper { 56 | Memory(InMemoryPool), 57 | Sqlite(SqlitePool), 58 | } 59 | 60 | #[async_trait] 61 | impl DbPoolCloseable for DbPoolCloseableWrapper { 62 | async fn close(self) { 63 | match self { 64 | DbPoolCloseableWrapper::Memory(db) => db.close().await, 65 | DbPoolCloseableWrapper::Sqlite(db) => db.close().await, 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /.github/workflows/check-test.yml: -------------------------------------------------------------------------------- 1 | name: check-test 2 | permissions: 3 | contents: read 4 | issues: read 5 | checks: write 6 | pull-requests: write 7 | 8 | on: 9 | workflow_dispatch: 10 | push: 11 | branches: 12 | - main 13 | - latest 14 | pull_request: 15 | 16 | # If new code is pushed to a PR branch, then cancel in progress workflows for that PR. 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 19 | cancel-in-progress: true 20 | 21 | defaults: 22 | run: 23 | shell: bash -xe {0} 24 | 25 | jobs: 26 | ci-test: 27 | runs-on: ubuntu-24.04 28 | steps: 29 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 30 | 31 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 32 | with: 33 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 34 | 35 | - name: Populate the nix store 36 | run: nix develop --command echo 37 | 38 | - name: Build tests 39 | run: nix develop --command cargo nextest run --workspace --all-features --no-run 40 | 41 | - name: Populate the codegen cache 42 | run: nix develop --command cargo nextest run --workspace --all-features --profile ci-test-populate-codegen-cache populate_codegen_cache --test-threads 1 43 | env: 44 | CI: true 45 | 46 | - name: cargo test 47 | env: 48 | RUST_LOG: "info,executor=trace,wasm_workers=trace,db=info" 49 | CI: true 50 | run: nix develop --command cargo nextest run --workspace --all-features --profile ${{ github.job }} 51 | 52 | - name: Upload test results 53 | uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f 54 | with: 55 | name: junit-report 56 | path: target/nextest/${{ github.job }}/junit.xml 57 | 58 | - name: Report results in GitHub UI 59 | uses: dorny/test-reporter@fe45e9537387dac839af0d33ba56eed8e24189e8 60 | if: always() 61 | with: 62 | name: Rust tests 63 | path: target/nextest/${{ github.job }}/junit.xml 64 | reporter: java-junit 65 | -------------------------------------------------------------------------------- /crates/testing/test-programs/fibo/workflow-outer/src/lib.rs: -------------------------------------------------------------------------------- 1 | use exports::testing::fibo_workflow_outer::workflow::Guest as GuestNesting; 2 | use obelisk::workflow::workflow_support::join_set_create; 3 | use wit_bindgen::generate; 4 | 5 | generate!({ generate_all }); 6 | struct Component; 7 | export!(Component); 8 | 9 | pub fn black_box(dummy: T) -> T { 10 | unsafe { 11 | let ret = std::ptr::read_volatile(&raw const dummy); 12 | std::mem::forget(dummy); 13 | ret 14 | } 15 | } 16 | 17 | impl GuestNesting for Component { 18 | // Start 2 child workflows each starting 2 child workflows... 19 | fn fibo_nested_workflow(n: u8) -> Result { 20 | use testing::fibo_workflow_outer::workflow::fibo_nested_workflow as imported_fibo_nested_workflow; 21 | if n <= 1 { 22 | Ok(1) 23 | } else { 24 | Ok(imported_fibo_nested_workflow(n - 1).unwrap() 25 | + imported_fibo_nested_workflow(n - 2).unwrap()) 26 | } 27 | } 28 | 29 | // Calls `fiboa` workflow concurrently. 30 | // Used for testing pressure of the parallel children results on the parent execution. 31 | // Having all children compete for write their result to a single parent, like 32 | // `fiboa_concurrent`, is significantly slower than having multiple parent executions 33 | // behind a single topmost parent. 34 | fn fibo_start_fiboas(n: u8, fiboas: u32, iterations_per_fiboa: u32) -> Result { 35 | use testing::fibo_workflow_obelisk_ext::workflow::{ 36 | fiboa_concurrent_await_next, fiboa_concurrent_submit, 37 | }; 38 | let join_set = join_set_create(); 39 | for _ in 0..fiboas { 40 | fiboa_concurrent_submit(&join_set, n, iterations_per_fiboa); 41 | } 42 | let mut last = 0; 43 | for _ in 0..fiboas { 44 | last = fiboa_concurrent_await_next(&join_set).unwrap().1.unwrap(); 45 | } 46 | Ok(last) 47 | } 48 | } 49 | 50 | #[must_use] 51 | pub fn fibo(n: u8) -> u64 { 52 | if n == 0 { 53 | 0 54 | } else if n == 1 { 55 | 1 56 | } else { 57 | fibo(n - 1) + fibo(n - 2) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__params@test_programs_fibo_workflow.wasm_exports.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: exports 4 | --- 5 | { 6 | "testing:fibo-workflow/workflow.fiboa": { 7 | "ffqn": "testing:fibo-workflow/workflow.fiboa", 8 | "parameter_types": [ 9 | { 10 | "type_wrapper": "u8", 11 | "name": "n", 12 | "wit_type": "u8" 13 | }, 14 | { 15 | "type_wrapper": "u32", 16 | "name": "iterations", 17 | "wit_type": "u32" 18 | } 19 | ], 20 | "return_type": { 21 | "Extendable": { 22 | "type_wrapper_tl": { 23 | "ok": "u64", 24 | "err": null 25 | }, 26 | "wit_type": "result" 27 | } 28 | }, 29 | "extension": null, 30 | "submittable": true 31 | }, 32 | "testing:fibo-workflow/workflow.fiboa-concurrent": { 33 | "ffqn": "testing:fibo-workflow/workflow.fiboa-concurrent", 34 | "parameter_types": [ 35 | { 36 | "type_wrapper": "u8", 37 | "name": "n", 38 | "wit_type": "u8" 39 | }, 40 | { 41 | "type_wrapper": "u32", 42 | "name": "iterations", 43 | "wit_type": "u32" 44 | } 45 | ], 46 | "return_type": { 47 | "Extendable": { 48 | "type_wrapper_tl": { 49 | "ok": "u64", 50 | "err": null 51 | }, 52 | "wit_type": "result" 53 | } 54 | }, 55 | "extension": null, 56 | "submittable": true 57 | }, 58 | "testing:fibo-workflow/workflow.fibow": { 59 | "ffqn": "testing:fibo-workflow/workflow.fibow", 60 | "parameter_types": [ 61 | { 62 | "type_wrapper": "u8", 63 | "name": "n", 64 | "wit_type": "u8" 65 | }, 66 | { 67 | "type_wrapper": "u32", 68 | "name": "iterations", 69 | "wit_type": "u32" 70 | } 71 | ], 72 | "return_type": { 73 | "Extendable": { 74 | "type_wrapper_tl": { 75 | "ok": "u64", 76 | "err": null 77 | }, 78 | "wit_type": "result" 79 | } 80 | }, 81 | "extension": null, 82 | "submittable": true 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /.github/workflows/release-5-verify-cargo-install.yml: -------------------------------------------------------------------------------- 1 | name: release-5-verify-cargo-install 2 | 3 | # Contrary to `check-run-cargo-install`, install latest Rust and run cargo install using sources from crates.io . 4 | 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | ref: 9 | description: "The ref (branch or SHA) to obtain the tag" 10 | required: false 11 | type: string 12 | workflow_run: 13 | workflows: 14 | - release-2-cargo-publish 15 | types: 16 | - completed 17 | 18 | defaults: 19 | run: 20 | shell: bash -xe {0} 21 | 22 | jobs: 23 | verify-assets: 24 | runs-on: ubuntu-24.04 25 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 26 | strategy: 27 | fail-fast: false 28 | steps: 29 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 30 | with: 31 | # Use the ref if provided, otherwise obtain the parent workflow branch, defaults to main. 32 | ref: ${{ github.event.inputs.ref || github.event.workflow_run.head_branch }} 33 | 34 | - id: git-info 35 | run: | 36 | VERSION="$(grep -m1 '^version = "' Cargo.toml | cut -d'"' -f2)" 37 | echo "version=$VERSION" >> $GITHUB_OUTPUT 38 | echo "tag=v$VERSION" >> $GITHUB_OUTPUT 39 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 40 | 41 | - name: Install latest Rust 42 | run: | 43 | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 44 | 45 | - name: Install dependencies 46 | run: | 47 | sudo apt update 48 | sudo apt install protobuf-compiler -y 49 | 50 | - name: Run cargo install 51 | run: | 52 | source "$HOME/.cargo/env" 53 | cargo install obelisk@$VERSION --locked 54 | env: 55 | VERSION: ${{ steps.git-info.outputs.version }} 56 | 57 | - name: Verify Obelisk 58 | run: | 59 | source "$HOME/.cargo/env" 60 | mkdir tmp # Avoid conflict with existing obelisk.toml 61 | cd tmp 62 | obelisk --version 63 | obelisk server generate-config 64 | obelisk server verify 65 | -------------------------------------------------------------------------------- /crates/utils/src/snapshots/obeli_sk_utils__wasm_tools__tests__exports_imports@test_programs_fibo_workflow.wasm_exports_noext.snap: -------------------------------------------------------------------------------- 1 | --- 2 | source: crates/utils/src/wasm_tools.rs 3 | expression: exports 4 | --- 5 | { 6 | "testing:fibo-workflow/workflow.fiboa": { 7 | "ffqn": "testing:fibo-workflow/workflow.fiboa", 8 | "parameter_types": [ 9 | { 10 | "type_wrapper": "u8", 11 | "name": "n", 12 | "wit_type": "u8" 13 | }, 14 | { 15 | "type_wrapper": "u32", 16 | "name": "iterations", 17 | "wit_type": "u32" 18 | } 19 | ], 20 | "return_type": { 21 | "Extendable": { 22 | "type_wrapper_tl": { 23 | "ok": "u64", 24 | "err": null 25 | }, 26 | "wit_type": "result" 27 | } 28 | }, 29 | "extension": null, 30 | "submittable": true 31 | }, 32 | "testing:fibo-workflow/workflow.fiboa-concurrent": { 33 | "ffqn": "testing:fibo-workflow/workflow.fiboa-concurrent", 34 | "parameter_types": [ 35 | { 36 | "type_wrapper": "u8", 37 | "name": "n", 38 | "wit_type": "u8" 39 | }, 40 | { 41 | "type_wrapper": "u32", 42 | "name": "iterations", 43 | "wit_type": "u32" 44 | } 45 | ], 46 | "return_type": { 47 | "Extendable": { 48 | "type_wrapper_tl": { 49 | "ok": "u64", 50 | "err": null 51 | }, 52 | "wit_type": "result" 53 | } 54 | }, 55 | "extension": null, 56 | "submittable": true 57 | }, 58 | "testing:fibo-workflow/workflow.fibow": { 59 | "ffqn": "testing:fibo-workflow/workflow.fibow", 60 | "parameter_types": [ 61 | { 62 | "type_wrapper": "u8", 63 | "name": "n", 64 | "wit_type": "u8" 65 | }, 66 | { 67 | "type_wrapper": "u32", 68 | "name": "iterations", 69 | "wit_type": "u32" 70 | } 71 | ], 72 | "return_type": { 73 | "Extendable": { 74 | "type_wrapper_tl": { 75 | "ok": "u64", 76 | "err": null 77 | }, 78 | "wit_type": "result" 79 | } 80 | }, 81 | "extension": null, 82 | "submittable": true 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /wit/wasi_cli@0.2.3/terminal.wit: -------------------------------------------------------------------------------- 1 | /// Terminal input. 2 | /// 3 | /// In the future, this may include functions for disabling echoing, 4 | /// disabling input buffering so that keyboard events are sent through 5 | /// immediately, querying supported features, and so on. 6 | @since(version = 0.2.0) 7 | interface terminal-input { 8 | /// The input side of a terminal. 9 | @since(version = 0.2.0) 10 | resource terminal-input; 11 | } 12 | 13 | /// Terminal output. 14 | /// 15 | /// In the future, this may include functions for querying the terminal 16 | /// size, being notified of terminal size changes, querying supported 17 | /// features, and so on. 18 | @since(version = 0.2.0) 19 | interface terminal-output { 20 | /// The output side of a terminal. 21 | @since(version = 0.2.0) 22 | resource terminal-output; 23 | } 24 | 25 | /// An interface providing an optional `terminal-input` for stdin as a 26 | /// link-time authority. 27 | @since(version = 0.2.0) 28 | interface terminal-stdin { 29 | @since(version = 0.2.0) 30 | use terminal-input.{terminal-input}; 31 | 32 | /// If stdin is connected to a terminal, return a `terminal-input` handle 33 | /// allowing further interaction with it. 34 | @since(version = 0.2.0) 35 | get-terminal-stdin: func() -> option; 36 | } 37 | 38 | /// An interface providing an optional `terminal-output` for stdout as a 39 | /// link-time authority. 40 | @since(version = 0.2.0) 41 | interface terminal-stdout { 42 | @since(version = 0.2.0) 43 | use terminal-output.{terminal-output}; 44 | 45 | /// If stdout is connected to a terminal, return a `terminal-output` handle 46 | /// allowing further interaction with it. 47 | @since(version = 0.2.0) 48 | get-terminal-stdout: func() -> option; 49 | } 50 | 51 | /// An interface providing an optional `terminal-output` for stderr as a 52 | /// link-time authority. 53 | @since(version = 0.2.0) 54 | interface terminal-stderr { 55 | @since(version = 0.2.0) 56 | use terminal-output.{terminal-output}; 57 | 58 | /// If stderr is connected to a terminal, return a `terminal-output` handle 59 | /// allowing further interaction with it. 60 | @since(version = 0.2.0) 61 | get-terminal-stderr: func() -> option; 62 | } 63 | -------------------------------------------------------------------------------- /.github/workflows/release-5-verify-github-release.yml: -------------------------------------------------------------------------------- 1 | name: release-5-verify-github-release 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | ref: 7 | description: "The ref (branch or SHA) to obtain the tag" 8 | required: false 9 | type: string 10 | workflow_run: 11 | workflows: 12 | - release-2-cargo-publish 13 | types: 14 | - completed 15 | 16 | defaults: 17 | run: 18 | shell: bash -xe {0} 19 | 20 | jobs: 21 | verify-assets: 22 | name: ${{ matrix.runner }}-${{ matrix.file }} 23 | runs-on: ${{ matrix.runner }} 24 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | include: 29 | - runner: ubuntu-22.04 30 | file: obelisk-x86_64-unknown-linux-gnu.tar.gz 31 | - runner: ubuntu-22.04 32 | file: obelisk-x86_64-unknown-linux-musl.tar.gz 33 | - runner: macos-14 34 | file: obelisk-x86_64-apple-darwin.tar.gz 35 | - runner: macos-14 36 | file: obelisk-aarch64-apple-darwin.tar.gz 37 | steps: 38 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 39 | with: 40 | # Use the ref if provided, otherwise obtain the parent workflow branch, defaults to main. 41 | ref: ${{ github.event.inputs.ref || github.event.workflow_run.head_branch }} 42 | 43 | - id: git-info 44 | run: | 45 | VERSION="$(grep -m1 '^version = "' Cargo.toml | cut -d'"' -f2)" 46 | echo "version=$VERSION" >> $GITHUB_OUTPUT 47 | echo "tag=v$VERSION" >> $GITHUB_OUTPUT 48 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 49 | 50 | - run: | 51 | mkdir temp 52 | cd temp 53 | # download the binary from GitHub Releases 54 | FILE="${{ matrix.file }}" 55 | curl --fail -L -o "$FILE" \ 56 | https://github.com/obeli-sk/obelisk/releases/download/$TAG/$FILE 57 | tar xzfv "$FILE" 58 | ./obelisk --version | grep $VERSION 59 | ./obelisk server generate-config 60 | ./obelisk server verify 61 | env: 62 | TAG: ${{ steps.git-info.outputs.tag }} 63 | VERSION: ${{ steps.git-info.outputs.version }} 64 | -------------------------------------------------------------------------------- /wit/obelisk_workflow@4.0.0/workflow-support.wit: -------------------------------------------------------------------------------- 1 | package obelisk:workflow@4.0.0; 2 | 3 | @since(version = 4.0.0) 4 | interface workflow-support { 5 | use obelisk:types/time@4.0.0.{schedule-at, datetime}; 6 | use obelisk:types/execution@4.0.0.{delay-id, execution-id, response-id}; 7 | use obelisk:types/join-set@4.0.0.{join-set}; 8 | 9 | /// Error variants that may occur on named join set creation. 10 | @since(version = 3.0.0) 11 | variant join-set-create-error { 12 | conflict, 13 | invalid-name(string), 14 | } 15 | 16 | /// Returns a random u64 in the range [min, max). 17 | @since(version = 3.0.0) 18 | random-u64: func(min: u64, max-exclusive: u64) -> u64; 19 | /// Returns a random u64 in the range [min, max]. 20 | @since(version = 3.0.0) 21 | random-u64-inclusive: func(min: u64, max-inclusive: u64) -> u64; 22 | 23 | /// Returns a random string with a length in the range [min_length, max_length). 24 | /// The string consists only of alphanumeric characters (lowercase and uppercase letters, digits). 25 | @since(version = 3.0.0) 26 | random-string: func(min-length: u16, max-length-exclusive: u16) -> string; 27 | 28 | /// Block execution for given time, return the time when the durable sleep expires. 29 | /// Returns error if the delay is cancelled. 30 | @since(version = 4.0.0) 31 | sleep: func(schedule-at: schedule-at) -> result; 32 | 33 | /// Create a new join set with a generated name. 34 | @since(version = 4.0.0) 35 | join-set-create: func() -> join-set; 36 | 37 | /// Create a new join set with the specified name. 38 | /// The name may only contain alphanumeric characters and the following extra characters: 39 | /// * underscore `_` 40 | /// * dash `-` 41 | /// * forward slash `/` 42 | @since(version = 4.0.0) 43 | join-set-create-named: func(name: string) -> result; 44 | 45 | /// Explicitly close join set. Unawaited delay requests are ignored, 46 | /// unawaited activities are cancelled, unawaited child workflows block 47 | /// until finish, as mandated by structured concurrency pattern. 48 | /// Extension function `-get` can be later used to lookup the execution result. 49 | @since(version = 4.0.0) 50 | join-set-close: func(self: join-set); 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-bump-flake-lock.yml: -------------------------------------------------------------------------------- 1 | name: scheduled-bump-flake-lock 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 0' # Runs every Sunday at 00:00 UTC 6 | workflow_dispatch: 7 | 8 | defaults: 9 | run: 10 | shell: bash -xe {0} 11 | 12 | permissions: 13 | contents: write 14 | pull-requests: write 15 | 16 | jobs: 17 | bump-cargo-lock: 18 | runs-on: ubuntu-24.04 19 | steps: 20 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 21 | with: 22 | fetch-depth: 1 23 | 24 | - name: Generate Unique Branch Name 25 | id: branch-name 26 | run: echo "branch_name=bump-cargo-lock-$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT 27 | 28 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 29 | with: 30 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 31 | 32 | - name: Bump flake.lock 33 | run: | 34 | nix flake update 35 | nix develop --command ./scripts/dev-deps.sh 36 | 37 | - name: Configure Git 38 | run: | 39 | git config user.name "github-actions[bot]" 40 | git config user.email "github-actions[bot]@users.noreply.github.com" 41 | 42 | - name: Commit Changes 43 | run: | 44 | git checkout -b ${{ steps.branch-name.outputs.branch_name }} 45 | git add . 46 | if [ -n "$(git status --porcelain)" ]; then 47 | git commit -m 'chore: Bump `flake.lock`' 48 | git push origin ${{ steps.branch-name.outputs.branch_name }} 49 | 50 | OWNER=$(echo "${{ github.repository }}" | cut -d'/' -f1) 51 | REPO=$(echo "${{ github.repository }}" | cut -d'/' -f2) 52 | curl -v --fail -X POST \ 53 | -H "Content-Type: application/json" \ 54 | -H "Authorization: Bearer $GITHUB_TOKEN" \ 55 | https://api.github.com/repos/$OWNER/$REPO/pulls \ 56 | -d '{ 57 | "title": "Bump `flake.lock`", 58 | "head": "'${{ steps.branch-name.outputs.branch_name }}'", 59 | "base": "main", 60 | "body": "" 61 | }' 62 | else 63 | echo "No changes to commit." 64 | fi 65 | env: 66 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PR_RW }} 67 | 68 | -------------------------------------------------------------------------------- /.github/workflows/release-2-cargo-publish.yml: -------------------------------------------------------------------------------- 1 | name: release-2-cargo-publish 2 | 3 | permissions: 4 | contents: write 5 | id-token: write 6 | attestations: write 7 | 8 | on: 9 | workflow_dispatch: 10 | inputs: 11 | ref: 12 | description: "The ref (branch or SHA) to process" 13 | required: false 14 | type: string 15 | default: "latest" 16 | update-main: 17 | description: "Should the branch `main` be updated?" 18 | required: false 19 | type: boolean 20 | default: true 21 | extra-args: 22 | description: "Extra args to be used with cargo publish e.g. --no-verify" 23 | type: string 24 | required: false 25 | default: "" 26 | skip_latest: 27 | description: "skip_latest: Tag latest will be pushed unless skip_latest=true" 28 | required: true 29 | type: boolean 30 | default: false 31 | 32 | defaults: 33 | run: 34 | shell: bash -xe {0} 35 | 36 | jobs: 37 | cargo-publish: 38 | runs-on: ubuntu-24.04 39 | steps: 40 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 41 | with: 42 | ref: ${{ github.event.inputs.ref }} # Use the ref if provided, otherwise defaults to the current branch/commit 43 | fetch-depth: 0 44 | 45 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 46 | with: 47 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 48 | 49 | - name: Configure git before push 50 | run: | 51 | git config user.name "github-actions[bot]" 52 | git config user.email "github-actions[bot]@users.noreply.github.com" 53 | 54 | - name: Run cargo publish 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_TOKEN }} 58 | run: | 59 | nix develop --command ./scripts/cargo-publish-workspace.sh --locked ${{ github.event.inputs.extra-args }} 60 | 61 | - name: Update `main` branch 62 | if: ${{ github.event.inputs.update-main }} 63 | run: | 64 | git push origin HEAD:main 65 | 66 | call_child: 67 | needs: cargo-publish 68 | uses: ./.github/workflows/release-3-create-github-release.yml 69 | secrets: inherit 70 | with: 71 | skip_latest: "${{inputs.skip_latest}}" 72 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1731533236, 9 | "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "nixpkgs": { 22 | "locked": { 23 | "lastModified": 1766070988, 24 | "narHash": "sha256-G/WVghka6c4bAzMhTwT2vjLccg/awmHkdKSd2JrycLc=", 25 | "owner": "NixOS", 26 | "repo": "nixpkgs", 27 | "rev": "c6245e83d836d0433170a16eb185cefe0572f8b8", 28 | "type": "github" 29 | }, 30 | "original": { 31 | "owner": "NixOS", 32 | "ref": "nixos-unstable", 33 | "repo": "nixpkgs", 34 | "type": "github" 35 | } 36 | }, 37 | "root": { 38 | "inputs": { 39 | "flake-utils": "flake-utils", 40 | "nixpkgs": "nixpkgs", 41 | "rust-overlay": "rust-overlay" 42 | } 43 | }, 44 | "rust-overlay": { 45 | "inputs": { 46 | "nixpkgs": [ 47 | "nixpkgs" 48 | ] 49 | }, 50 | "locked": { 51 | "lastModified": 1766198367, 52 | "narHash": "sha256-f1L1rCEu2Zew6zdiZ38jJDZd65ktE7UN+Gqn2LHPiFI=", 53 | "owner": "oxalica", 54 | "repo": "rust-overlay", 55 | "rev": "66bb33fdfb50b1ee724381c3f5d6012dac6c89b3", 56 | "type": "github" 57 | }, 58 | "original": { 59 | "owner": "oxalica", 60 | "repo": "rust-overlay", 61 | "type": "github" 62 | } 63 | }, 64 | "systems": { 65 | "locked": { 66 | "lastModified": 1681028828, 67 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 68 | "owner": "nix-systems", 69 | "repo": "default", 70 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 71 | "type": "github" 72 | }, 73 | "original": { 74 | "owner": "nix-systems", 75 | "repo": "default", 76 | "type": "github" 77 | } 78 | } 79 | }, 80 | "root": "root", 81 | "version": 7 82 | } 83 | -------------------------------------------------------------------------------- /wit/wasi_clocks@0.2.3/timezone.wit: -------------------------------------------------------------------------------- 1 | package wasi:clocks@0.2.3; 2 | 3 | @unstable(feature = clocks-timezone) 4 | interface timezone { 5 | @unstable(feature = clocks-timezone) 6 | use wall-clock.{datetime}; 7 | 8 | /// Return information needed to display the given `datetime`. This includes 9 | /// the UTC offset, the time zone name, and a flag indicating whether 10 | /// daylight saving time is active. 11 | /// 12 | /// If the timezone cannot be determined for the given `datetime`, return a 13 | /// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight 14 | /// saving time. 15 | @unstable(feature = clocks-timezone) 16 | display: func(when: datetime) -> timezone-display; 17 | 18 | /// The same as `display`, but only return the UTC offset. 19 | @unstable(feature = clocks-timezone) 20 | utc-offset: func(when: datetime) -> s32; 21 | 22 | /// Information useful for displaying the timezone of a specific `datetime`. 23 | /// 24 | /// This information may vary within a single `timezone` to reflect daylight 25 | /// saving time adjustments. 26 | @unstable(feature = clocks-timezone) 27 | record timezone-display { 28 | /// The number of seconds difference between UTC time and the local 29 | /// time of the timezone. 30 | /// 31 | /// The returned value will always be less than 86400 which is the 32 | /// number of seconds in a day (24*60*60). 33 | /// 34 | /// In implementations that do not expose an actual time zone, this 35 | /// should return 0. 36 | utc-offset: s32, 37 | 38 | /// The abbreviated name of the timezone to display to a user. The name 39 | /// `UTC` indicates Coordinated Universal Time. Otherwise, this should 40 | /// reference local standards for the name of the time zone. 41 | /// 42 | /// In implementations that do not expose an actual time zone, this 43 | /// should be the string `UTC`. 44 | /// 45 | /// In time zones that do not have an applicable name, a formatted 46 | /// representation of the UTC offset may be returned, such as `-04:00`. 47 | name: string, 48 | 49 | /// Whether daylight saving time is active. 50 | /// 51 | /// In implementations that do not expose an actual time zone, this 52 | /// should return false. 53 | in-daylight-saving-time: bool, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /.github/workflows/release-3-create-github-release.yml: -------------------------------------------------------------------------------- 1 | name: release-3-create-github-release 2 | 3 | permissions: 4 | contents: write 5 | id-token: write 6 | attestations: write 7 | 8 | on: 9 | workflow_dispatch: 10 | inputs: 11 | ref: 12 | description: "The ref (branch or SHA) to process" 13 | required: false 14 | type: string 15 | workflow_call: 16 | inputs: 17 | skip_latest: 18 | description: "skip_latest: Tag latest will be pushed unless skip_latest=true" 19 | required: true 20 | type: boolean 21 | default: false 22 | defaults: 23 | run: 24 | shell: bash -xe {0} 25 | 26 | jobs: 27 | create-github-release: 28 | runs-on: ubuntu-24.04 29 | steps: 30 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 31 | with: 32 | # Use the ref if provided, otherwise obtain the parent workflow branch, defaults to main. 33 | ref: ${{ github.event.inputs.ref || github.event.workflow_run.head_branch }} 34 | 35 | - id: git-info 36 | run: | 37 | VERSION="$(grep -m1 '^version = "' Cargo.toml | cut -d'"' -f2)" 38 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 39 | echo "tag=v$VERSION" >> $GITHUB_OUTPUT 40 | echo "version=$VERSION" >> $GITHUB_OUTPUT 41 | 42 | - name: Create GitHub Release 43 | run: | 44 | echo "Releasing $TAG $SHA" 45 | body=$(./scripts/extract-release-info.sh "$VERSION" | jq -R -s .) 46 | curl -v --fail -X POST \ 47 | -H "Content-Type: application/json" \ 48 | -H "Authorization: Bearer $GITHUB_TOKEN" \ 49 | -d '{ 50 | "tag_name": "'"$TAG"'", 51 | "target_commitish": "'"$SHA"'", 52 | "name": "obelisk-'"$TAG"'", 53 | "body": '"$body"', 54 | "draft": false, 55 | "prerelease": false 56 | }' \ 57 | https://api.github.com/repos/obeli-sk/obelisk/releases 58 | env: 59 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 60 | SHA: ${{ steps.git-info.outputs.sha }} 61 | TAG: ${{ steps.git-info.outputs.tag }} 62 | VERSION: ${{ steps.git-info.outputs.version }} 63 | 64 | call_child: 65 | needs: create-github-release 66 | uses: ./.github/workflows/release-3.1-upload-artifacts.yml 67 | secrets: inherit 68 | with: 69 | skip_latest: "${{inputs.skip_latest}}" 70 | -------------------------------------------------------------------------------- /crates/testing/test-programs/http/workflow/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate::obelisk::log::log; 2 | use exports::testing::http_workflow::workflow::Guest; 3 | use obelisk::workflow::workflow_support::join_set_create; 4 | use testing::{ 5 | http::http_get, 6 | http_obelisk_ext::http_get::{get_successful_await_next, get_successful_submit}, 7 | }; 8 | use wit_bindgen::generate; 9 | 10 | generate!({ generate_all }); 11 | struct Component; 12 | export!(Component); 13 | 14 | impl Guest for Component { 15 | fn get(url: String) -> Result { 16 | http_get::get(&url) 17 | } 18 | 19 | fn get_resp(url: String) -> Result { 20 | let resp = http_get::get_resp(&url)?; 21 | Ok(String::from_utf8_lossy(&resp.body).into_owned()) 22 | } 23 | 24 | fn get_successful(url: String) -> Result { 25 | http_get::get_successful(&url) 26 | } 27 | 28 | fn get_successful_concurrently(urls: Vec) -> Result, String> { 29 | let join_set = join_set_create(); 30 | let length = urls.len(); 31 | for url in urls { 32 | let _execution_id = get_successful_submit(&join_set, &url); 33 | } 34 | let mut list = Vec::with_capacity(length); 35 | for _ in 0..length { 36 | // Mark the whole result as failed if any child execution fails. 37 | let contents = get_successful_await_next(&join_set).unwrap().1?; 38 | list.push(contents); 39 | } 40 | Ok(list) 41 | } 42 | 43 | fn get_successful_concurrently_stress( 44 | url: String, 45 | concurrency: u32, 46 | ) -> Result, String> { 47 | let join_set = join_set_create(); 48 | let join_set_id = join_set.id(); 49 | log::info(&format!("Created join set {join_set_id}")); 50 | assert_eq!("g:1", join_set_id); 51 | for _ in 0..concurrency { 52 | let _execution_id = get_successful_submit(&join_set, &url); 53 | } 54 | let mut list = Vec::with_capacity(concurrency as usize); 55 | for _ in 0..concurrency { 56 | // Mark the whole result as failed if any child execution fails. 57 | let contents = get_successful_await_next(&join_set).unwrap().1?; 58 | list.push(contents); 59 | } 60 | Ok(list) 61 | } 62 | 63 | fn get_stargazers() -> Result<(), ()> { 64 | http_get::get_stargazers().unwrap(); 65 | Ok(()) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /.github/workflows/release-5-verify-run-nix.yml: -------------------------------------------------------------------------------- 1 | name: release-5-verify-run-nix 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | ref: 7 | description: "The ref (branch or SHA) to obtain the tag" 8 | required: false 9 | type: string 10 | workflow_run: 11 | workflows: 12 | - release-2-cargo-publish 13 | types: 14 | - completed 15 | 16 | defaults: 17 | run: 18 | shell: bash -xe {0} 19 | 20 | jobs: 21 | check-run-nix: 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | include: 26 | - target: default 27 | os: ubuntu-24.04 28 | - target: default 29 | os: ubuntu-24.04-arm 30 | 31 | runs-on: ${{ matrix.os }} 32 | if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} 33 | steps: 34 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 35 | with: 36 | # Use the ref if provided, otherwise obtain the parent workflow branch, defaults to main. 37 | ref: ${{ github.event.inputs.ref || github.event.workflow_run.head_branch }} 38 | 39 | - id: git-info 40 | run: | 41 | VERSION="$(grep -m1 '^version = "' Cargo.toml | cut -d'"' -f2)" 42 | echo "version=$VERSION" >> $GITHUB_OUTPUT 43 | echo "tag=v$VERSION" >> $GITHUB_OUTPUT 44 | echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 45 | 46 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 47 | with: 48 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 49 | - name: Populate the nix store without Obelisk # Workaround for slow garnix cache 50 | run: | 51 | nix develop --command echo 52 | - name: Add garnix cache 53 | run: | 54 | echo "extra-substituters = https://cache.garnix.io" >> ~/.config/nix/nix.conf 55 | echo "extra-trusted-public-keys = cache.garnix.io:CTFPyKSLcx5RMJKfLo5EEPUObbA78b0YQ2DTCJXqr9g" >> ~/.config/nix/nix.conf 56 | 57 | - name: Create temp directory 58 | run: mkdir temp 59 | 60 | - name: Build the binary 61 | working-directory: temp 62 | run: | 63 | full_target="github:obeli-sk/obelisk/${TAG}#${{ matrix.target }}" 64 | nix run $full_target -- --version 65 | nix run $full_target -- server generate-config 66 | nix run $full_target -- server verify 67 | env: 68 | TAG: ${{ steps.git-info.outputs.tag }} 69 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | permissions: 3 | contents: read 4 | # This configuration allows maintainers of this repo to create a branch and pull request based on 5 | # the new branch. Restricting the push trigger to the main branch ensures that the PR only gets 6 | # built once. 7 | on: 8 | push: 9 | branches: 10 | - main 11 | - latest 12 | pull_request: 13 | 14 | # If new code is pushed to a PR branch, then cancel in progress workflows for that PR. 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 17 | cancel-in-progress: true 18 | 19 | defaults: 20 | run: 21 | shell: bash -xe {0} 22 | 23 | jobs: 24 | fmt: 25 | name: cargo fmt 26 | runs-on: ubuntu-24.04 27 | steps: 28 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 29 | 30 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 31 | with: 32 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 33 | - name: Populate the nix store 34 | run: nix develop --command echo 35 | 36 | - name: cargo fmt 37 | run: nix develop --command cargo fmt --check 38 | 39 | check-dev-deps: 40 | name: Check dev-deps.txt 41 | runs-on: ubuntu-24.04 42 | steps: 43 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 44 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 45 | with: 46 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 47 | - name: Populate the nix store 48 | run: nix develop --command echo 49 | 50 | - run: nix develop --command ./scripts/dev-deps.sh 51 | - run: | 52 | if git diff --quiet; then 53 | echo "No changes" 54 | else 55 | echo "::error::Changes in dev-deps.txt detected" 56 | git diff 57 | exit 1 58 | fi 59 | 60 | clippy: 61 | name: clippy 62 | runs-on: ubuntu-24.04 63 | strategy: 64 | fail-fast: false 65 | steps: 66 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 67 | 68 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 69 | with: 70 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 71 | 72 | - name: Populate the nix store 73 | run: nix develop --command echo 74 | 75 | - name: cargo clippy 76 | run: nix develop --command cargo clippy --workspace --all-targets -- -D warnings 77 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod args; 2 | mod command; 3 | mod config; 4 | mod env_vars; 5 | mod init; 6 | mod oci; 7 | mod server; 8 | 9 | use args::{Args, Client, ClientSubcommand, Subcommand}; 10 | use clap::Parser; 11 | use directories::ProjectDirs; 12 | use grpc::{grpc_gen, injector::TracingInjector}; 13 | use tonic::{codec::CompressionEncoding, transport::Channel}; 14 | 15 | #[tokio::main] 16 | async fn main() -> Result<(), anyhow::Error> { 17 | match Args::parse().command { 18 | Subcommand::Server(server) => server.run().await, 19 | Subcommand::Client(Client { 20 | api_url, 21 | command: ClientSubcommand::Component(component), 22 | }) => component.run(&api_url).await, 23 | Subcommand::Client(Client { 24 | api_url, 25 | command: ClientSubcommand::Execution(execution), 26 | }) => execution.run(&api_url).await, 27 | Subcommand::Generate(generate) => generate.run().await, 28 | } 29 | } 30 | 31 | pub(crate) fn project_dirs() -> Option { 32 | ProjectDirs::from("", "obelisk", "obelisk") 33 | } 34 | 35 | type ExecutionRepositoryClient = grpc_gen::execution_repository_client::ExecutionRepositoryClient< 36 | tonic::service::interceptor::InterceptedService, 37 | >; 38 | 39 | async fn get_execution_repository_client( 40 | channel: Channel, 41 | ) -> Result { 42 | Ok( 43 | grpc_gen::execution_repository_client::ExecutionRepositoryClient::with_interceptor( 44 | channel, 45 | TracingInjector, 46 | ) 47 | .send_compressed(CompressionEncoding::Zstd) 48 | .accept_compressed(CompressionEncoding::Zstd) 49 | .accept_compressed(CompressionEncoding::Gzip), 50 | ) 51 | } 52 | type FunctionRepositoryClient = grpc_gen::function_repository_client::FunctionRepositoryClient< 53 | tonic::service::interceptor::InterceptedService, 54 | >; 55 | async fn get_fn_repository_client( 56 | channel: Channel, 57 | ) -> Result { 58 | Ok( 59 | grpc_gen::function_repository_client::FunctionRepositoryClient::with_interceptor( 60 | channel, 61 | TracingInjector, 62 | ) 63 | .send_compressed(CompressionEncoding::Zstd) 64 | .accept_compressed(CompressionEncoding::Zstd) 65 | .accept_compressed(CompressionEncoding::Gzip), 66 | ) 67 | } 68 | 69 | #[derive(Copy, Clone, PartialEq, Eq, PartialOrd)] 70 | enum FunctionMetadataVerbosity { 71 | ExportsOnly, 72 | ExportsAndImports, 73 | } 74 | -------------------------------------------------------------------------------- /crates/wasm-workers/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "obeli-sk-wasm-workers" 3 | description = "Internal package of obeli-sk" 4 | 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | repository.workspace = true 9 | rust-version.workspace = true 10 | version.workspace = true 11 | 12 | [dependencies] 13 | concepts.workspace = true 14 | executor.workspace = true 15 | utils.workspace = true 16 | val-json.workspace = true 17 | 18 | arbitrary.workspace = true 19 | assert_matches.workspace = true 20 | async-trait.workspace = true 21 | bytes.workspace = true 22 | chrono.workspace = true 23 | const_format.workspace = true 24 | derive_more.workspace = true 25 | hashbrown.workspace = true 26 | http-body-util.workspace = true 27 | hyper-util.workspace = true 28 | hyper.workspace = true 29 | indexmap.workspace = true 30 | itertools.workspace = true 31 | libc.workspace = true 32 | rand.workspace = true 33 | route-recognizer.workspace = true 34 | serde_json.workspace = true 35 | serde.workspace = true 36 | strum.workspace = true 37 | thiserror.workspace = true 38 | tokio.workspace = true 39 | tracing.workspace = true 40 | ulid.workspace = true 41 | wasmtime-wasi-http.workspace = true 42 | wasmtime-wasi-io.workspace = true 43 | wasmtime-wasi.workspace = true 44 | wasmtime.workspace = true 45 | 46 | [features] 47 | test = [] 48 | 49 | [dev-dependencies] 50 | concepts = { workspace = true, features = ["test"] } 51 | db-mem.workspace = true 52 | db-sqlite = { workspace = true, features = ["tempfile"] } 53 | db-tests.workspace = true 54 | executor = { workspace = true, features = ["test"] } 55 | insta.workspace = true 56 | serde_json.workspace = true 57 | test-programs-dir-activity-builder.workspace = true 58 | test-programs-fibo-activity-builder.workspace = true 59 | test-programs-fibo-webhook-builder.workspace = true 60 | test-programs-fibo-workflow-builder.workspace = true 61 | test-programs-http-get-activity-builder.workspace = true 62 | test-programs-http-get-workflow-builder.workspace = true 63 | test-programs-process-activity-builder.workspace = true 64 | test-programs-serde-activity-builder.workspace = true 65 | test-programs-serde-workflow-builder.workspace = true 66 | test-programs-sleep-activity-builder.workspace = true 67 | test-programs-sleep-workflow-builder.workspace = true 68 | test-programs-stub-activity-builder.workspace = true 69 | test-programs-stub-workflow-builder.workspace = true 70 | test-utils.workspace = true 71 | utils.workspace = true 72 | 73 | async-trait.workspace = true 74 | futures-util.workspace = true 75 | reqwest.workspace = true 76 | rstest.workspace = true 77 | tempfile.workspace = true 78 | wiremock.workspace = true 79 | 80 | [lints] 81 | workspace = true 82 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-bump-cargo-lock.yml: -------------------------------------------------------------------------------- 1 | name: scheduled-bump-cargo-lock 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 6' # Runs every Saturday at 00:00 UTC 6 | workflow_dispatch: 7 | 8 | defaults: 9 | run: 10 | shell: bash -xe {0} 11 | 12 | permissions: 13 | contents: write 14 | pull-requests: write 15 | 16 | jobs: 17 | bump-cargo-lock: 18 | runs-on: ubuntu-24.04 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | include: 23 | - name: compatible 24 | cmd: cargo upgrade 25 | - name: incompatible 26 | cmd: cargo upgrade --incompatible 27 | 28 | steps: 29 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 30 | with: 31 | fetch-depth: 1 32 | 33 | - name: Generate Unique Branch Name 34 | id: branch-name 35 | run: echo "branch_name=bump-flake-lock-${{ matrix.name }}-$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT 36 | 37 | - uses: nixbuild/nix-quick-install-action@2c9db80fb984ceb1bcaa77cdda3fdf8cfba92035 38 | with: 39 | github_access_token: ${{ secrets.GITHUB_TOKEN }} 40 | 41 | - name: Populate the nix store 42 | run: | 43 | nix develop --command echo 44 | 45 | - name: Bump Cargo.lock, Cargo.toml 46 | run: | 47 | nix develop --command ${{ matrix.cmd }} 48 | 49 | - name: Configure Git 50 | run: | 51 | git config user.name "github-actions[bot]" 52 | git config user.email "github-actions[bot]@users.noreply.github.com" 53 | 54 | - name: Commit Changes 55 | run: | 56 | git checkout -b ${{ steps.branch-name.outputs.branch_name }} 57 | git add Cargo.lock Cargo.toml 58 | if [ -n "$(git status --porcelain)" ]; then 59 | git commit -m "chore: Bump Rust dependencies" 60 | git push origin ${{ steps.branch-name.outputs.branch_name }} 61 | 62 | OWNER=$(echo "${{ github.repository }}" | cut -d'/' -f1) 63 | REPO=$(echo "${{ github.repository }}" | cut -d'/' -f2) 64 | curl -v --fail -X POST \ 65 | -H "Content-Type: application/json" \ 66 | -H "Authorization: Bearer $GITHUB_TOKEN" \ 67 | https://api.github.com/repos/$OWNER/$REPO/pulls \ 68 | -d '{ 69 | "title": "Bump Rust dependencies", 70 | "head": "'${{ steps.branch-name.outputs.branch_name }}'", 71 | "base": "main", 72 | "body": "" 73 | }' 74 | else 75 | echo "No changes to commit." 76 | fi 77 | env: 78 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN_PR_RW }} 79 | 80 | -------------------------------------------------------------------------------- /release-plz.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | semver_check = false # disable API breaking changes checks 3 | changelog_update = false 4 | git_release_enable = false 5 | git_tag_enable = false 6 | 7 | [[package]] 8 | name = "obelisk" 9 | git_tag_name = "v{{ version }}" 10 | git_tag_enable = true 11 | git_release_enable = true 12 | 13 | changelog_update = true 14 | changelog_include = [ 15 | "obeli-sk-concepts", 16 | "obeli-sk-db-sqlite", 17 | "obeli-sk-executor", 18 | "obeli-sk-utils", 19 | "obeli-sk-val-json", 20 | "obeli-sk-wasm-workers", 21 | ] 22 | 23 | [changelog] 24 | header = """# Changelog 25 | All notable changes to this project will be documented in this file. 26 | 27 | ## [Unreleased] 28 | """ 29 | body = """ 30 | 31 | {% macro print_commit(commit) -%} 32 | - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ 33 | {% if commit.breaking %}[**breaking**] {% endif %}\ 34 | {{ commit.message | upper_first }} - \ 35 | ([{{ commit.id | truncate(length=7, end="") }}]({{ remote.link }}/commit/{{ commit.id }}))\ 36 | {% endmacro -%} 37 | 38 | {% if version %}\ 39 | {% if previous.version %}\ 40 | ## [{{ version | trim_start_matches(pat="v") }}]({{ release_link }}) 41 | {% else %}\ 42 | ## [{{ version | trim_start_matches(pat="v") }}] 43 | {% endif %}\ 44 | {% endif %}\ 45 | 46 | {% for group, commits in commits 47 | | filter(attribute="merge_commit", value=false) 48 | | unique(attribute="message") 49 | | group_by(attribute="group") %} 50 | ### {{ group | striptags | trim | upper_first }} 51 | {% for commit in commits 52 | | filter(attribute="scope") 53 | | sort(attribute="scope") %} 54 | {{ self::print_commit(commit=commit) }} 55 | {%- endfor -%} 56 | {% raw %}\n{% endraw %}\ 57 | {%- for commit in commits %} 58 | {%- if not commit.scope -%} 59 | {{ self::print_commit(commit=commit) }} 60 | {% endif -%} 61 | {% endfor -%} 62 | {% endfor %}\n 63 | """ 64 | 65 | commit_parsers = [ 66 | { message = "^feat", group = "⛰️ Features" }, 67 | { message = "^fix", group = "🐛 Bug Fixes" }, 68 | { message = "^doc", group = "📚 Documentation" }, 69 | { message = "^perf", group = "⚡ Performance" }, 70 | { body = ".*security", group = "🛡️ Security" }, 71 | { message = "^revert", group = "◀️ Revert" }, 72 | { message = "^refactor", group = "🚜 Refactor" }, 73 | { message = "^test", skip = true }, 74 | { message = "^style", skip = true }, 75 | { message = "^chore", skip = true }, 76 | { message = "^ci", skip = true }, 77 | { message = "^build", skip = true }, 78 | { message = "^logging", skip = true }, 79 | { message = "^tracing", skip = true }, 80 | ] 81 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod config_holder; 2 | pub(crate) mod env_var; 3 | pub(crate) mod toml; 4 | 5 | use crate::oci; 6 | use anyhow::Context; 7 | use concepts::ComponentId; 8 | use concepts::ContentDigest; 9 | use concepts::FunctionMetadata; 10 | use concepts::PackageIfcFns; 11 | use config_holder::PathPrefixes; 12 | use schemars::JsonSchema; 13 | use serde::Deserialize; 14 | use serde_with::serde_as; 15 | use std::path::{Path, PathBuf}; 16 | use toml::ConfigName; 17 | use tracing::instrument; 18 | use utils::sha256sum::calculate_sha256_file; 19 | 20 | /// Holds information about components, used for gRPC services like `ListComponents` 21 | #[derive(Debug, Clone)] 22 | pub(crate) struct ComponentConfig { 23 | pub(crate) component_id: ComponentId, 24 | pub(crate) imports: Vec, 25 | pub(crate) workflow_or_activity_config: Option, 26 | pub(crate) wit: Option, 27 | } 28 | 29 | #[derive(Debug, Clone)] 30 | // Workflows or Activities (WASM, stub), but not Webhooks 31 | pub(crate) struct ComponentConfigImportable { 32 | pub(crate) exports_ext: Vec, 33 | pub(crate) exports_hierarchy_ext: Vec, 34 | } 35 | 36 | #[derive(Debug, Clone, Hash)] 37 | pub(crate) struct ConfigStoreCommon { 38 | pub(crate) name: ConfigName, 39 | pub(crate) location: ComponentLocation, 40 | pub(crate) content_digest: ContentDigest, 41 | } 42 | 43 | #[serde_as] 44 | #[derive(Debug, Clone, Hash, Deserialize, JsonSchema)] 45 | #[serde(rename_all = "snake_case")] 46 | pub(crate) enum ComponentLocation { 47 | Path(String), 48 | Oci( 49 | #[serde_as(as = "serde_with::DisplayFromStr")] 50 | #[schemars(with = "String")] 51 | oci_client::Reference, 52 | ), 53 | } 54 | 55 | impl ComponentLocation { 56 | #[instrument(skip_all)] 57 | pub(crate) async fn obtain_wasm( 58 | &self, 59 | wasm_cache_dir: &Path, 60 | metadata_dir: &Path, 61 | path_prefixes: &PathPrefixes, 62 | ) -> Result<(ContentDigest, PathBuf), anyhow::Error> { 63 | match self { 64 | ComponentLocation::Path(wasm_path) => { 65 | let wasm_path = path_prefixes.replace_file_prefix_verify_exists(wasm_path)?; 66 | // Future optimization: If the content digest is specified in TOML and wasm is already in the cache dir, do not recalculate it. 67 | let content_digest = calculate_sha256_file(&wasm_path) 68 | .await 69 | .with_context(|| format!("cannot compute hash of file `{wasm_path:?}`"))?; 70 | Ok((content_digest, wasm_path)) 71 | } 72 | ComponentLocation::Oci(image) => { 73 | oci::pull_to_cache_dir(image, wasm_cache_dir, metadata_dir) 74 | .await 75 | .context("try cleaning the cache directory with `--clean-cache`") 76 | } 77 | } 78 | } 79 | } 80 | --------------------------------------------------------------------------------