diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e49ae34..0c3b048 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: rust: [stable, beta] include: - os: ubuntu-latest - rust: nightly + rust: nightly-2026-04-16 steps: - name: Checkout sources uses: actions/checkout@v6 @@ -119,6 +119,8 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2026-04-16 - name: Cache cargo registry uses: actions/cache@v5 @@ -143,9 +145,11 @@ jobs: - name: Install Rust nightly toolchain uses: dtolnay/rust-toolchain@nightly + with: + toolchain: nightly-2026-04-16 - name: Install cargo-udeps uses: taiki-e/install-action@cargo-udeps - name: Check for unused dependencies - run: cargo +nightly udeps --all-targets --all-features + run: cargo udeps --all-targets --all-features diff --git a/.sqlx/query-066be74a69b4e3f45a1e7c0cd85896b26ba97059de53ebb5773d6d9d4dfbbec7.json b/.sqlx/query-066be74a69b4e3f45a1e7c0cd85896b26ba97059de53ebb5773d6d9d4dfbbec7.json new file mode 100644 index 0000000..27de918 --- /dev/null +++ b/.sqlx/query-066be74a69b4e3f45a1e7c0cd85896b26ba97059de53ebb5773d6d9d4dfbbec7.json @@ -0,0 +1,21 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO\n apalis.jobs (\n id,\n job_type,\n job,\n status,\n attempts,\n max_attempts,\n run_at,\n priority,\n metadata,\n idempotency_key\n )\nSELECT\n unnest($1::text[]) as id,\n $2::text as job_type,\n unnest($3::bytea[]) as job,\n 'Pending' as status,\n 0 as attempts,\n unnest($4::integer []) as max_attempts,\n unnest($5::timestamptz []) as run_at,\n unnest($6::integer []) as priority,\n unnest($7::jsonb []) as metadata,\n unnest($8::text []) as idempotency_key\n", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "TextArray", + "Text", + "ByteaArray", + "Int4Array", + "TimestamptzArray", + "Int4Array", + "JsonbArray", + "TextArray" + ] + }, + "nullable": [] + }, + "hash": "066be74a69b4e3f45a1e7c0cd85896b26ba97059de53ebb5773d6d9d4dfbbec7" +} diff --git a/.sqlx/query-1989cc0be6f389d4211ebd23cfa961105f4df7c023b50b0da3acae8881d4d010.json b/.sqlx/query-1989cc0be6f389d4211ebd23cfa961105f4df7c023b50b0da3acae8881d4d010.json index 7008f4e..d3e59a1 100644 --- a/.sqlx/query-1989cc0be6f389d4211ebd23cfa961105f4df7c023b50b0da3acae8881d4d010.json +++ b/.sqlx/query-1989cc0be6f389d4211ebd23cfa961105f4df7c023b50b0da3acae8881d4d010.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -88,6 +93,7 @@ true, true, true, + true, true ] }, diff --git a/.sqlx/query-6ce4a9f7891abb2452136bef3a9d9065d452490dc7dde0d6f0590838f386f39c.json b/.sqlx/query-6ce4a9f7891abb2452136bef3a9d9065d452490dc7dde0d6f0590838f386f39c.json index aed4ae7..17bd9bb 100644 --- a/.sqlx/query-6ce4a9f7891abb2452136bef3a9d9065d452490dc7dde0d6f0590838f386f39c.json +++ b/.sqlx/query-6ce4a9f7891abb2452136bef3a9d9065d452490dc7dde0d6f0590838f386f39c.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -88,6 +93,7 @@ true, true, true, + true, true ] }, diff --git a/.sqlx/query-7e5fb4248558ac31dd2b4ff2c34a58930c43feb8ee8c4505e0a4e0521ee6890c.json b/.sqlx/query-7e5fb4248558ac31dd2b4ff2c34a58930c43feb8ee8c4505e0a4e0521ee6890c.json deleted file mode 100644 index 511c1ee..0000000 --- a/.sqlx/query-7e5fb4248558ac31dd2b4ff2c34a58930c43feb8ee8c4505e0a4e0521ee6890c.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO\n apalis.jobs (\n id,\n job_type,\n job,\n status,\n attempts,\n max_attempts,\n run_at,\n priority,\n metadata\n )\nSELECT\n unnest($1::text[]) as id,\n $2::text as job_type,\n unnest($3::bytea[]) as job,\n 'Pending' as status,\n 0 as attempts,\n unnest($4::integer []) as max_attempts,\n unnest($5::timestamptz []) as run_at,\n unnest($6::integer []) as priority,\n unnest($7::jsonb []) as metadata\n", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "TextArray", - "Text", - "ByteaArray", - "Int4Array", - "TimestamptzArray", - "Int4Array", - "JsonbArray" - ] - }, - "nullable": [] - }, - "hash": "7e5fb4248558ac31dd2b4ff2c34a58930c43feb8ee8c4505e0a4e0521ee6890c" -} diff --git a/.sqlx/query-a0dcac1deb02eb19959aedcde6e8864a459891ff9b5447882bcd6a43856b91f4.json b/.sqlx/query-a0dcac1deb02eb19959aedcde6e8864a459891ff9b5447882bcd6a43856b91f4.json index b196afe..dbbc532 100644 --- a/.sqlx/query-a0dcac1deb02eb19959aedcde6e8864a459891ff9b5447882bcd6a43856b91f4.json +++ b/.sqlx/query-a0dcac1deb02eb19959aedcde6e8864a459891ff9b5447882bcd6a43856b91f4.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -87,6 +92,7 @@ true, true, true, + true, true ] }, diff --git a/.sqlx/query-aec15451aa407010d95e6014b0e6b4a361a6cc85c26c56ea82cdd2c37a123dac.json b/.sqlx/query-aec15451aa407010d95e6014b0e6b4a361a6cc85c26c56ea82cdd2c37a123dac.json index e3cc46d..f2e478f 100644 --- a/.sqlx/query-aec15451aa407010d95e6014b0e6b4a361a6cc85c26c56ea82cdd2c37a123dac.json +++ b/.sqlx/query-aec15451aa407010d95e6014b0e6b4a361a6cc85c26c56ea82cdd2c37a123dac.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -90,6 +95,7 @@ true, true, true, + true, true ] }, diff --git a/.sqlx/query-fc3801ddf6016402eb1ab46da4e6d733992fd5b98269ad25c25dc9e9d7a1db0a.json b/.sqlx/query-fc3801ddf6016402eb1ab46da4e6d733992fd5b98269ad25c25dc9e9d7a1db0a.json index e2aad84..4d0cc06 100644 --- a/.sqlx/query-fc3801ddf6016402eb1ab46da4e6d733992fd5b98269ad25c25dc9e9d7a1db0a.json +++ b/.sqlx/query-fc3801ddf6016402eb1ab46da4e6d733992fd5b98269ad25c25dc9e9d7a1db0a.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -89,6 +94,7 @@ null, null, null, + null, null ] }, diff --git a/.sqlx/query-fe90494e81b507098f8b8704e8d61500f5e81da8d38ffd1e03db0148eb889c78.json b/.sqlx/query-fe90494e81b507098f8b8704e8d61500f5e81da8d38ffd1e03db0148eb889c78.json index 3f5b84e..e44d383 100644 --- a/.sqlx/query-fe90494e81b507098f8b8704e8d61500f5e81da8d38ffd1e03db0148eb889c78.json +++ b/.sqlx/query-fe90494e81b507098f8b8704e8d61500f5e81da8d38ffd1e03db0148eb889c78.json @@ -67,6 +67,11 @@ "ordinal": 12, "name": "metadata", "type_info": "Jsonb" + }, + { + "ordinal": 13, + "name": "idempotency_key", + "type_info": "Text" } ], "parameters": { @@ -89,6 +94,7 @@ true, true, true, + true, true ] }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 43d4c7f..9cdd27a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- feat: idempotency for tasks (#81) +- chore: make JsonCodec publicly accessible (#79) + ## [1.0.0-rc.7] - 2026-04-09 - bump: introducing rc.7 diff --git a/Cargo.lock b/Cargo.lock index e2adcd0..c0cbc0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "apalis" -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ca73a2477b3e6cf2650296c0441149ba50c40506b5aeb8ba75399e81181ce0" +checksum = "7780d1e7082500a4fdb463b0a6fc1c00e4012cd9b2af101c26fcabbb2f390f2c" dependencies = [ "apalis-core", "futures-util", @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "apalis-codec" -version = "0.1.0-rc.7" +version = "0.1.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f45e8249032bc5ed2c515471eca7913282190d8d8e7679cebf9b8fc6af40400a" +checksum = "c506e7f00c7c9c38eeb02290b3ec6328695f0614a257faefaeb8e8286746a665" dependencies = [ "apalis-core", "serde", @@ -50,9 +50,9 @@ dependencies = [ [[package]] name = "apalis-core" -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc053b8daf9235fd974cf2a7d7f8ed7ee8108ba1736d3ecce20529d26c32f66" +checksum = "797af42a40f6bc297365f2fed187b74d089c63641f57ce2a5e0f629db560cb47" dependencies = [ "futures-channel", "futures-core", @@ -91,9 +91,9 @@ dependencies = [ [[package]] name = "apalis-sql" -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5adc4a7c146226036d44baed2862dc2ee22b7299d19e7c4941fd27e1267a45a" +checksum = "09b555912820da093b004a055105af258df116edcea761db6b759d01aabac2ec" dependencies = [ "apalis-core", "chrono", @@ -105,9 +105,9 @@ dependencies = [ [[package]] name = "apalis-workflow" -version = "0.1.0-rc.7" +version = "0.1.0-rc.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d223e7ce6a21e22c4da5ff9a5b82e57578544a73dda04718f8a2801dd13847" +checksum = "9392c07db462a5c0befec5d6685a37d9ec2424a244b7e7e021208c5c9544cef0" dependencies = [ "apalis-core", "futures", @@ -302,9 +302,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ "serde_core", ] @@ -351,9 +351,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.59" +version = "1.2.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", "shlex", @@ -430,9 +430,9 @@ dependencies = [ [[package]] name = "crc-catalog" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" +checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" [[package]] name = "crossbeam-queue" @@ -844,9 +844,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "hashlink" @@ -1033,9 +1033,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1043,12 +1043,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] @@ -1081,9 +1081,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08" dependencies = [ "cfg-if", "futures-util", @@ -1117,9 +1117,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.184" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libm" @@ -1129,14 +1129,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "libc", "plain", - "redox_syscall 0.7.3", + "redox_syscall 0.7.5", ] [[package]] @@ -1240,7 +1240,7 @@ dependencies = [ "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -1289,15 +1289,14 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "openssl" -version = "0.10.76" +version = "0.10.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "951c002c75e16ea2c65b8c7e4d3d51d5530d8dfa7d060b4776828c88cfb18ecf" +checksum = "bf0b434746ee2832f4f0baf10137e1cabb18cbe6912c69e2e33263c45250f542" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -1321,9 +1320,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.112" +version = "0.9.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d55af3b3e226502be1526dfdba67ab0e9c96fc293004e79576b2b9edb0dbdb" +checksum = "158fe5b292746440aa6e7a7e690e55aeb72d41505e2804c23c6973ad0e9c9781" dependencies = [ "cc", "libc", @@ -1390,18 +1389,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.11" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" dependencies = [ "proc-macro2", "quote", @@ -1454,9 +1453,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plain" @@ -1560,9 +1559,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -1571,9 +1570,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -1623,16 +1622,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] name = "redox_syscall" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" +checksum = "4666a1a60d8412eab19d94f6d13dcc9cea0a5ef4fdf6a5db306537413c661b1b" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", ] [[package]] @@ -1689,7 +1688,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "errno", "libc", "linux-raw-sys 0.12.1", @@ -1698,9 +1697,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.37" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "once_cell", "ring", @@ -1712,18 +1711,18 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.10" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "ring", "rustls-pki-types", @@ -1763,7 +1762,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "core-foundation", "core-foundation-sys", "libc", @@ -2034,7 +2033,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64", - "bitflags 2.11.0", + "bitflags 2.11.1", "byteorder", "bytes", "chrono", @@ -2056,7 +2055,7 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", - "rand 0.8.5", + "rand 0.8.6", "rsa", "serde", "sha1", @@ -2078,7 +2077,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64", - "bitflags 2.11.0", + "bitflags 2.11.1", "byteorder", "chrono", "crc", @@ -2096,7 +2095,7 @@ dependencies = [ "md-5", "memchr", "once_cell", - "rand 0.8.5", + "rand 0.8.6", "serde", "serde_json", "sha2", @@ -2277,9 +2276,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.51.1" +version = "1.52.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" +checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" dependencies = [ "bytes", "libc", @@ -2388,9 +2387,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "ulid" @@ -2398,7 +2397,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ - "rand 0.9.2", + "rand 0.9.4", "serde", "web-time", ] @@ -2492,11 +2491,11 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] @@ -2505,7 +2504,7 @@ version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.51.0", ] [[package]] @@ -2516,9 +2515,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790" dependencies = [ "cfg-if", "once_cell", @@ -2529,9 +2528,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.67" +version = "0.4.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +checksum = "96492d0d3ffba25305a7dc88720d250b1401d7edca02cc3bcd50633b424673b8" dependencies = [ "js-sys", "wasm-bindgen", @@ -2539,9 +2538,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2549,9 +2548,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2" dependencies = [ "bumpalo", "proc-macro2", @@ -2562,9 +2561,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441" dependencies = [ "unicode-ident", ] @@ -2597,7 +2596,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags 2.11.1", "hashbrown 0.15.5", "indexmap", "semver", @@ -2619,14 +2618,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -2879,6 +2878,12 @@ dependencies = [ "wit-bindgen-rust-macro", ] +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + [[package]] name = "wit-bindgen-core" version = "0.51.0" @@ -2928,7 +2933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags 2.11.1", "indexmap", "log", "serde", diff --git a/deny.toml b/deny.toml index f555596..132b797 100644 --- a/deny.toml +++ b/deny.toml @@ -37,6 +37,7 @@ skip-tree = [ { name = "rand" }, { name = "rand_chacha" }, { name = "rand_core" }, + { name = "redox_syscall" }, ] [sources] diff --git a/examples/stepped.rs b/examples/stepped.rs index 8ca8ccb..3e4ac11 100644 --- a/examples/stepped.rs +++ b/examples/stepped.rs @@ -9,8 +9,6 @@ async fn main() { let workflow = Workflow::new("odd-numbers-workflow") .and_then(|a: usize| async move { Ok::<_, BoxDynError>((0..=a).collect::>()) }) .filter_map(|x| async move { if x % 2 != 0 { Some(x) } else { None } }) - .filter_map(|x| async move { if x % 3 != 0 { Some(x) } else { None } }) - .filter_map(|x| async move { if x % 5 != 0 { Some(x) } else { None } }) .delay_for(Duration::from_millis(1000)) .and_then( |a: Vec, ctx: WorkerContext, task_id: PgTaskId| async move { diff --git a/examples/unique_jobs.rs b/examples/unique_jobs.rs new file mode 100644 index 0000000..837f08b --- /dev/null +++ b/examples/unique_jobs.rs @@ -0,0 +1,39 @@ +use apalis::prelude::*; +use apalis_postgres::PostgresStorage; +use sqlx::PgPool; + +#[tokio::main] +async fn main() { + let dedupe_key = "c76b5ceb-1538-411d-b755-f654e4f53680"; + + let pool = PgPool::connect(&std::env::var("DATABASE_URL").unwrap()) + .await + .unwrap(); + PostgresStorage::setup(&pool).await.unwrap(); + let mut backend = PostgresStorage::new(&pool); + + let task_1 = TaskBuilder::new(42) + .with_idempotency_key(dedupe_key) + .build(); + + let task_2 = TaskBuilder::new(43) + .with_idempotency_key(dedupe_key) + .build(); + + backend.push_task(task_1).await.unwrap(); + backend.push_task(task_2).await.unwrap(); + + async fn task(task: u32, worker: WorkerContext) -> Result<(), BoxDynError> { + apalis_core::timer::sleep(std::time::Duration::from_secs(1)).await; + assert_eq!(task, 42); + worker.stop()?; + Ok(()) + } + let worker = WorkerBuilder::new("rango-tango") + .backend(backend) + .on_event(|ctx, e| { + println!("{e:?}"); + }) + .build(task); + worker.run().await.unwrap(); +} diff --git a/migrations/20260508093314_idempotency_key.sql b/migrations/20260508093314_idempotency_key.sql new file mode 100644 index 0000000..8aa3c72 --- /dev/null +++ b/migrations/20260508093314_idempotency_key.sql @@ -0,0 +1,6 @@ +ALTER TABLE + apalis.jobs +ADD + COLUMN idempotency_key TEXT; + +CREATE UNIQUE INDEX idx_jobs_idempotency_key ON apalis.jobs(job_type, idempotency_key); diff --git a/queries/task/sink.sql b/queries/task/sink.sql index e992e87..917f83b 100644 --- a/queries/task/sink.sql +++ b/queries/task/sink.sql @@ -8,7 +8,8 @@ INSERT INTO max_attempts, run_at, priority, - metadata + metadata, + idempotency_key ) SELECT unnest($1::text[]) as id, @@ -19,4 +20,5 @@ SELECT unnest($4::integer []) as max_attempts, unnest($5::timestamptz []) as run_at, unnest($6::integer []) as priority, - unnest($7::jsonb []) as metadata + unnest($7::jsonb []) as metadata, + unnest($8::text []) as idempotency_key diff --git a/src/from_row.rs b/src/from_row.rs index ebe07cd..b197386 100644 --- a/src/from_row.rs +++ b/src/from_row.rs @@ -14,6 +14,7 @@ pub struct PgTaskRow { pub lock_by: Option, pub done_at: Option, pub priority: Option, + pub idempotency_key: Option, pub metadata: Option, } impl TryInto for PgTaskRow { @@ -42,6 +43,7 @@ impl TryInto for PgTaskRow { lock_by: self.lock_by, done_at: self.done_at, priority: self.priority.map(|v| v as usize), + idempotency_key: self.idempotency_key, metadata: self.metadata, }) } diff --git a/src/queries/list_tasks.rs b/src/queries/list_tasks.rs index 47594ec..6c0f919 100644 --- a/src/queries/list_tasks.rs +++ b/src/queries/list_tasks.rs @@ -17,10 +17,9 @@ where { fn list_tasks( &self, - queue: &str, filter: &Filter, ) -> impl Future>, Self::Error>> + Send { - let queue = queue.to_string(); + let queue = self.config.queue().to_string(); let pool = self.pool.clone(); let limit = filter.limit() as i64; let offset = filter.offset() as i64; diff --git a/src/queries/list_workers.rs b/src/queries/list_workers.rs index 0b21fe2..ca2feaf 100644 --- a/src/queries/list_workers.rs +++ b/src/queries/list_workers.rs @@ -20,11 +20,9 @@ where PostgresStorage: BackendExt, { - fn list_workers( - &self, - queue: &str, - ) -> impl Future, Self::Error>> + Send { - let queue = queue.to_string(); + fn list_workers(&self) -> impl Future, Self::Error>> + Send { + let queue = self.config.queue().to_string(); + let pool = self.pool.clone(); let limit = 100; let offset = 0; diff --git a/src/queries/metrics.rs b/src/queries/metrics.rs index 5785a33..689abac 100644 --- a/src/queries/metrics.rs +++ b/src/queries/metrics.rs @@ -33,12 +33,9 @@ where Ok(rec) } } - fn fetch_by_queue( - &self, - queue_id: &str, - ) -> impl Future, Self::Error>> + Send { + fn fetch_by_queue(&self) -> impl Future, Self::Error>> + Send { let pool = self.pool.clone(); - let queue_id = queue_id.to_string(); + let queue_id = self.config.queue().to_string(); async move { let rec = sqlx::query_file_as!( StatisticRow, diff --git a/src/sink.rs b/src/sink.rs index 7ee2d34..cfd5f01 100644 --- a/src/sink.rs +++ b/src/sink.rs @@ -54,6 +54,7 @@ where let mut priorities = Vec::new(); let mut max_attempts_vec = Vec::new(); let mut metadata = Vec::new(); + let mut idempotency_key: Vec> = Vec::new(); for task in buffer { ids.push( @@ -69,6 +70,7 @@ where priorities.push(task.parts.ctx.priority()); max_attempts_vec.push(task.parts.ctx.max_attempts()); metadata.push(serde_json::Value::Object(task.parts.ctx.meta().clone())); + idempotency_key.push(task.parts.idempotency_key); } sqlx::query_file!( @@ -79,7 +81,8 @@ where &max_attempts_vec, &run_ats, &priorities, - &metadata + &metadata, + &idempotency_key as &[Option] ) .execute(conn) .map_ok(|_| ()) diff --git a/supply-chain/config.toml b/supply-chain/config.toml index ef272ae..0cf7513 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -20,15 +20,15 @@ version = "1.0.102" criteria = "safe-to-deploy" [[exemptions.apalis]] -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" criteria = "safe-to-run" [[exemptions.apalis-codec]] -version = "0.1.0-rc.7" +version = "0.1.0-rc.9" criteria = "safe-to-deploy" [[exemptions.apalis-core]] -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" criteria = "safe-to-deploy" [[exemptions.apalis-postgres]] @@ -36,11 +36,11 @@ version = "1.0.0-beta.3" criteria = "safe-to-deploy" [[exemptions.apalis-sql]] -version = "1.0.0-rc.7" +version = "1.0.0-rc.9" criteria = "safe-to-deploy" [[exemptions.apalis-workflow]] -version = "0.1.0-rc.7" +version = "0.1.0-rc.9" criteria = "safe-to-run" [[exemptions.async-channel]] @@ -108,7 +108,7 @@ version = "1.3.2" criteria = "safe-to-deploy" [[exemptions.bitflags]] -version = "2.11.0" +version = "2.11.1" criteria = "safe-to-deploy" [[exemptions.block-buffer]] @@ -132,7 +132,7 @@ version = "1.11.1" criteria = "safe-to-deploy" [[exemptions.cc]] -version = "1.2.59" +version = "1.2.61" criteria = "safe-to-deploy" [[exemptions.cfg-if]] @@ -168,7 +168,7 @@ version = "3.4.0" criteria = "safe-to-deploy" [[exemptions.crc-catalog]] -version = "2.4.0" +version = "2.5.0" criteria = "safe-to-deploy" [[exemptions.crossbeam-queue]] @@ -344,7 +344,7 @@ version = "0.15.5" criteria = "safe-to-deploy" [[exemptions.hashbrown]] -version = "0.16.1" +version = "0.17.0" criteria = "safe-to-deploy" [[exemptions.hashlink]] @@ -424,11 +424,11 @@ version = "1.1.0" criteria = "safe-to-deploy" [[exemptions.idna_adapter]] -version = "1.2.1" +version = "1.2.2" criteria = "safe-to-deploy" [[exemptions.indexmap]] -version = "2.13.1" +version = "2.14.0" criteria = "safe-to-deploy" [[exemptions.instant]] @@ -444,7 +444,7 @@ version = "1.0.18" criteria = "safe-to-deploy" [[exemptions.js-sys]] -version = "0.3.94" +version = "0.3.98" criteria = "safe-to-deploy" [[exemptions.kv-log-macro]] @@ -460,7 +460,7 @@ version = "0.1.0" criteria = "safe-to-deploy" [[exemptions.libc]] -version = "0.2.184" +version = "0.2.186" criteria = "safe-to-deploy" [[exemptions.libm]] @@ -468,7 +468,7 @@ version = "0.2.16" criteria = "safe-to-deploy" [[exemptions.libredox]] -version = "0.1.15" +version = "0.1.16" criteria = "safe-to-deploy" [[exemptions.libsqlite3-sys]] @@ -536,7 +536,7 @@ version = "1.21.4" criteria = "safe-to-deploy" [[exemptions.openssl]] -version = "0.10.76" +version = "0.10.79" criteria = "safe-to-deploy" [[exemptions.openssl-macros]] @@ -548,7 +548,7 @@ version = "0.2.1" criteria = "safe-to-deploy" [[exemptions.openssl-sys]] -version = "0.9.112" +version = "0.9.115" criteria = "safe-to-deploy" [[exemptions.parking]] @@ -576,11 +576,11 @@ version = "0.8.3" criteria = "safe-to-run" [[exemptions.pin-project]] -version = "1.1.11" +version = "1.1.12" criteria = "safe-to-deploy" [[exemptions.pin-project-internal]] -version = "1.1.11" +version = "1.1.12" criteria = "safe-to-deploy" [[exemptions.pin-project-lite]] @@ -604,7 +604,7 @@ version = "0.10.2" criteria = "safe-to-deploy" [[exemptions.pkg-config]] -version = "0.3.32" +version = "0.3.33" criteria = "safe-to-deploy" [[exemptions.plain]] @@ -652,11 +652,11 @@ version = "6.0.0" criteria = "safe-to-deploy" [[exemptions.rand]] -version = "0.8.5" +version = "0.8.6" criteria = "safe-to-deploy" [[exemptions.rand]] -version = "0.9.2" +version = "0.9.4" criteria = "safe-to-deploy" [[exemptions.rand_chacha]] @@ -680,7 +680,7 @@ version = "0.5.18" criteria = "safe-to-deploy" [[exemptions.redox_syscall]] -version = "0.7.3" +version = "0.7.5" criteria = "safe-to-deploy" [[exemptions.ring]] @@ -700,15 +700,15 @@ version = "1.1.4" criteria = "safe-to-deploy" [[exemptions.rustls]] -version = "0.23.37" +version = "0.23.40" criteria = "safe-to-deploy" [[exemptions.rustls-pki-types]] -version = "1.14.0" +version = "1.14.1" criteria = "safe-to-deploy" [[exemptions.rustls-webpki]] -version = "0.103.10" +version = "0.103.13" criteria = "safe-to-deploy" [[exemptions.rustversion]] @@ -888,7 +888,7 @@ version = "0.1.1" criteria = "safe-to-deploy" [[exemptions.tokio]] -version = "1.51.1" +version = "1.52.2" criteria = "safe-to-deploy" [[exemptions.tokio-macros]] @@ -928,7 +928,7 @@ version = "0.1.36" criteria = "safe-to-deploy" [[exemptions.typenum]] -version = "1.19.0" +version = "1.20.0" criteria = "safe-to-deploy" [[exemptions.ulid]] @@ -988,7 +988,7 @@ version = "0.11.1+wasi-snapshot-preview1" criteria = "safe-to-deploy" [[exemptions.wasip2]] -version = "1.0.2+wasi-0.2.9" +version = "1.0.3+wasi-0.2.9" criteria = "safe-to-deploy" [[exemptions.wasip3]] @@ -1000,23 +1000,23 @@ version = "0.1.0" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen]] -version = "0.2.117" +version = "0.2.121" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-futures]] -version = "0.4.67" +version = "0.4.71" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-macro]] -version = "0.2.117" +version = "0.2.121" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-macro-support]] -version = "0.2.117" +version = "0.2.121" criteria = "safe-to-deploy" [[exemptions.wasm-bindgen-shared]] -version = "0.2.117" +version = "0.2.121" criteria = "safe-to-deploy" [[exemptions.wasm-encoder]] @@ -1040,7 +1040,7 @@ version = "0.26.11" criteria = "safe-to-deploy" [[exemptions.webpki-roots]] -version = "1.0.6" +version = "1.0.7" criteria = "safe-to-deploy" [[exemptions.whoami]] @@ -1167,6 +1167,10 @@ criteria = "safe-to-deploy" version = "0.51.0" criteria = "safe-to-deploy" +[[exemptions.wit-bindgen]] +version = "0.57.1" +criteria = "safe-to-deploy" + [[exemptions.wit-bindgen-core]] version = "0.51.0" criteria = "safe-to-deploy"