diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b12bb83..b1401e9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -65,7 +65,11 @@ jobs: tox-${{ matrix.python }}-${{ hashFiles('requirements/*.txt') }}- - name: Run tox - run: tox -e py,coverage-report,typing + uses: lsst-sqre/run-tox@v1 + with: + python-version: ${{ matrix.python }} + tox-envs: 'lint,typing,py,coverage-report' + tox-plugins: "tox-docker" build: runs-on: ubuntu-latest diff --git a/requirements/dev.in b/requirements/dev.in index 57ced9c..cd112db 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -20,4 +20,4 @@ types-PyYAML # Documentation documenteer[guide]==1.0.0a1 -sphinx-click +sphinx-click \ No newline at end of file diff --git a/requirements/dev.txt b/requirements/dev.txt index 985401f..fd676e2 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -531,33 +531,33 @@ mdurl==0.1.2 \ # via # -c requirements/main.txt # markdown-it-py -mypy==1.3.0 \ - --hash=sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703 \ - --hash=sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf \ - --hash=sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4 \ - --hash=sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85 \ - --hash=sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd \ - --hash=sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae \ - --hash=sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd \ - --hash=sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca \ - --hash=sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305 \ - --hash=sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409 \ - --hash=sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c \ - --hash=sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb \ - --hash=sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee \ - --hash=sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a \ - --hash=sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228 \ - --hash=sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897 \ - --hash=sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d \ - --hash=sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f \ - --hash=sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152 \ - --hash=sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf \ - --hash=sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8 \ - --hash=sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11 \ - --hash=sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017 \ - --hash=sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929 \ - --hash=sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e \ - --hash=sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a +mypy==1.4.1 \ + --hash=sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042 \ + --hash=sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd \ + --hash=sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2 \ + --hash=sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01 \ + --hash=sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7 \ + --hash=sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3 \ + --hash=sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816 \ + --hash=sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3 \ + --hash=sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc \ + --hash=sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4 \ + --hash=sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b \ + --hash=sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8 \ + --hash=sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c \ + --hash=sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462 \ + --hash=sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7 \ + --hash=sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc \ + --hash=sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258 \ + --hash=sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b \ + --hash=sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9 \ + --hash=sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6 \ + --hash=sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f \ + --hash=sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1 \ + --hash=sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828 \ + --hash=sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878 \ + --hash=sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f \ + --hash=sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b # via -r requirements/dev.in mypy-extensions==1.0.0 \ --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \ @@ -567,35 +567,32 @@ myst-parser==1.0.0 \ --hash=sha256:502845659313099542bd38a2ae62f01360e7dd4b1310f025dd014dfc0439cdae \ --hash=sha256:69fb40a586c6fa68995e6521ac0a525793935db7e724ca9bac1d33be51be9a4c # via documenteer -numpy==1.24.3 \ - --hash=sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187 \ - --hash=sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812 \ - --hash=sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7 \ - --hash=sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4 \ - --hash=sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6 \ - --hash=sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0 \ - --hash=sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4 \ - --hash=sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570 \ - --hash=sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4 \ - --hash=sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f \ - --hash=sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80 \ - --hash=sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289 \ - --hash=sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385 \ - --hash=sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078 \ - --hash=sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c \ - --hash=sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463 \ - --hash=sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3 \ - --hash=sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950 \ - --hash=sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155 \ - --hash=sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7 \ - --hash=sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c \ - --hash=sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096 \ - --hash=sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17 \ - --hash=sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf \ - --hash=sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4 \ - --hash=sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02 \ - --hash=sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c \ - --hash=sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b +numpy==1.25.0 \ + --hash=sha256:0ac6edfb35d2a99aaf102b509c8e9319c499ebd4978df4971b94419a116d0790 \ + --hash=sha256:26815c6c8498dc49d81faa76d61078c4f9f0859ce7817919021b9eba72b425e3 \ + --hash=sha256:4aedd08f15d3045a4e9c648f1e04daca2ab1044256959f1f95aafeeb3d794c16 \ + --hash=sha256:4c69fe5f05eea336b7a740e114dec995e2f927003c30702d896892403df6dbf0 \ + --hash=sha256:5177310ac2e63d6603f659fadc1e7bab33dd5a8db4e0596df34214eeab0fee3b \ + --hash=sha256:5aa48bebfb41f93043a796128854b84407d4df730d3fb6e5dc36402f5cd594c0 \ + --hash=sha256:5b1b90860bf7d8a8c313b372d4f27343a54f415b20fb69dd601b7efe1029c91e \ + --hash=sha256:6c284907e37f5e04d2412950960894b143a648dea3f79290757eb878b91acbd1 \ + --hash=sha256:6d183b5c58513f74225c376643234c369468e02947b47942eacbb23c1671f25d \ + --hash=sha256:7412125b4f18aeddca2ecd7219ea2d2708f697943e6f624be41aa5f8a9852cc4 \ + --hash=sha256:7cd981ccc0afe49b9883f14761bb57c964df71124dcd155b0cba2b591f0d64b9 \ + --hash=sha256:85cdae87d8c136fd4da4dad1e48064d700f63e923d5af6c8c782ac0df8044542 \ + --hash=sha256:8aa130c3042052d656751df5e81f6d61edff3e289b5994edcf77f54118a8d9f4 \ + --hash=sha256:95367ccd88c07af21b379be1725b5322362bb83679d36691f124a16357390153 \ + --hash=sha256:9c7211d7920b97aeca7b3773a6783492b5b93baba39e7c36054f6e749fc7490c \ + --hash=sha256:9e3f2b96e3b63c978bc29daaa3700c028fe3f049ea3031b58aa33fe2a5809d24 \ + --hash=sha256:b76aa836a952059d70a2788a2d98cb2a533ccd46222558b6970348939e55fc24 \ + --hash=sha256:b792164e539d99d93e4e5e09ae10f8cbe5466de7d759fc155e075237e0c274e4 \ + --hash=sha256:c0dc071017bc00abb7d7201bac06fa80333c6314477b3d10b52b58fa6a6e38f6 \ + --hash=sha256:cc3fda2b36482891db1060f00f881c77f9423eead4c3579629940a3e12095fe8 \ + --hash=sha256:d6b267f349a99d3908b56645eebf340cb58f01bd1e773b4eea1a905b3f0e4208 \ + --hash=sha256:d76a84998c51b8b68b40448ddd02bd1081bb33abcdc28beee6cd284fe11036c6 \ + --hash=sha256:e559c6afbca484072a98a51b6fa466aae785cfe89b69e8b856c3191bc8872a82 \ + --hash=sha256:ecc68f11404930e9c7ecfc937aa423e1e50158317bf67ca91736a9864eae0232 \ + --hash=sha256:f1accae9a28dc3cda46a91de86acf69de0d1b5f4edd44a9b0c3ceb8036dfff19 # via # contourpy # matplotlib @@ -675,9 +672,9 @@ pillow==9.5.0 \ --hash=sha256:fe7e1c262d3392afcf5071df9afa574544f28eac825284596ac6db56e6d11062 \ --hash=sha256:fed1e1cf6a42577953abbe8e6cf2fe2f566daebde7c34724ec8803c4c0cda579 # via matplotlib -pluggy==1.0.0 \ - --hash=sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159 \ - --hash=sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 +pluggy==1.2.0 \ + --hash=sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849 \ + --hash=sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3 # via pytest psutil==5.9.5 \ --hash=sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d \ @@ -756,9 +753,9 @@ pygments==2.15.1 \ # pydata-sphinx-theme # sphinx # sphinx-prompt -pyparsing==3.0.9 \ - --hash=sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb \ - --hash=sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc +pyparsing==3.1.0 \ + --hash=sha256:d554a96d1a7d3ddaf7183104485bc19fd80543ad6ac5bdb6426719d766fb06c1 \ + --hash=sha256:edb662d6fe322d6e990b1594b5feaeadf806803359e3d4d42f11e295e588f0ea # via matplotlib pyrsistent==0.19.3 \ --hash=sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8 \ @@ -789,9 +786,9 @@ pyrsistent==0.19.3 \ --hash=sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9 \ --hash=sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c # via jsonschema -pytest==7.3.2 \ - --hash=sha256:cdcbd012c9312258922f8cd3f1b62a6580fdced17db6014896053d47cddf9295 \ - --hash=sha256:ee990a3cc55ba808b80795a79944756f315c67c12b56abd3ac993a7b8c17030b +pytest==7.4.0 \ + --hash=sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32 \ + --hash=sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a # via # -r requirements/dev.in # pytest-asyncio @@ -994,9 +991,9 @@ types-pyyaml==6.0.12.10 \ --hash=sha256:662fa444963eff9b68120d70cda1af5a5f2aa57900003c2006d7626450eaae5f \ --hash=sha256:ebab3d0700b946553724ae6ca636ea932c1b0868701d4af121630e78d695fc97 # via -r requirements/dev.in -typing-extensions==4.6.3 \ - --hash=sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26 \ - --hash=sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5 +typing-extensions==4.7.0 \ + --hash=sha256:5d8c9dac95c27d20df12fb1d97b9793ab8b2af8a3a525e68c80e21060c161771 \ + --hash=sha256:935ccf31549830cda708b42289d44b6f74084d616a00be651601a4f968e77c82 # via # -c requirements/main.txt # mypy diff --git a/requirements/main.in b/requirements/main.in index 4bcfc41..0761054 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -18,7 +18,7 @@ arrow click httpx python-dateutil -safir>=2.0 +safir[arq,redis]>=4.0 structlog pydantic markdown-it-py[linkify,plugins]<3.0.0 # for mdformat compatibility diff --git a/requirements/main.txt b/requirements/main.txt index b318707..f43c703 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -15,6 +15,10 @@ anyio==3.7.0 \ # httpcore # starlette # watchfiles +arq==0.25.0 \ + --hash=sha256:d176ebadfba920c039dc578814d19b7814d67fa15f82fdccccaedb4330d65dae \ + --hash=sha256:db072d0f39c0bc06b436db67ae1f315c81abc1527563b828955670531815290b + # via safir arrow==1.2.3 \ --hash=sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1 \ --hash=sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2 @@ -96,6 +100,7 @@ click==8.1.3 \ --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 # via # -r requirements/main.in + # arq # uvicorn cryptography==41.0.1 \ --hash=sha256:059e348f9a3c1950937e1b5d7ba1f8e968508ab181e75fc32b879452f08356db \ @@ -120,9 +125,9 @@ cryptography==41.0.1 \ # via # pyjwt # safir -fastapi==0.97.0 \ - --hash=sha256:95d757511c596409930bd20673358d4a4d709004edb85c5d24d6ffc48fabcbf2 \ - --hash=sha256:b53248ee45f64f19bb7600953696e3edf94b0f7de94df1e5433fc5c6136fa986 +fastapi==0.98.0 \ + --hash=sha256:0d3c18886f652038262b5898fec6b09f4ca92ee23e9d9b1d1d24e429f84bf27b \ + --hash=sha256:f4165fb1fe3610c52cb1b8282c1480de9c34bc270f56a965aa93a884c350d605 # via # -r requirements/main.in # safir @@ -204,6 +209,97 @@ h11==0.14.0 \ # via # httpcore # uvicorn +hiredis==2.2.3 \ + --hash=sha256:071c5814b850574036506a8118034f97c3cbf2fe9947ff45a27b07a48da56240 \ + --hash=sha256:08415ea74c1c29b9d6a4ca3dd0e810dc1af343c1d1d442e15ba133b11ab5be6a \ + --hash=sha256:126623b03c31cb6ac3e0d138feb6fcc36dd43dd34fc7da7b7a0c38b5d75bc896 \ + --hash=sha256:14824e457e4f5cda685c3345d125da13949bcf3bb1c88eb5d248c8d2c3dee08f \ + --hash=sha256:15c2a551f3b8a26f7940d6ee10b837810201754b8d7e6f6b1391655370882c5a \ + --hash=sha256:17e938d9d3ee92e1adbff361706f1c36cc60eeb3e3eeca7a3a353eae344f4c91 \ + --hash=sha256:1cadb0ac7ba3babfd804e425946bec9717b320564a1390f163a54af9365a720a \ + --hash=sha256:1d274d5c511dfc03f83f997d3238eaa9b6ee3f982640979f509373cced891e98 \ + --hash=sha256:20f509e3a1a20d6e5f5794fc37ceb21f70f409101fcfe7a8bde783894d51b369 \ + --hash=sha256:227c5b4bcb60f89008c275d596e4a7b6625a6b3c827b8a66ae582eace7051f71 \ + --hash=sha256:232d0a70519865741ba56e1dfefd160a580ae78c30a1517bad47b3cf95a3bc7d \ + --hash=sha256:2443659c76b226267e2a04dbbb21bc2a3f91aa53bdc0c22964632753ae43a247 \ + --hash=sha256:2d7e459fe7313925f395148d36d9b7f4f8dac65be06e45d7af356b187cef65fc \ + --hash=sha256:2fb9300959a0048138791f3d68359d61a788574ec9556bddf1fec07f2dbc5320 \ + --hash=sha256:334f2738700b20faa04a0d813366fb16ed17287430a6b50584161d5ad31ca6d7 \ + --hash=sha256:33a94d264e6e12a79d9bb8af333b01dc286b9f39c99072ab5fef94ce1f018e17 \ + --hash=sha256:33bc4721632ef9708fa44e5df0066053fccc8e65410a2c48573192517a533b48 \ + --hash=sha256:33ee3ea5cad3a8cb339352cd230b411eb437a2e75d7736c4899acab32056ccdb \ + --hash=sha256:3753df5f873d473f055e1f8837bfad0bd3b277c86f3c9bf058c58f14204cd901 \ + --hash=sha256:3759f4789ae1913b7df278dfc9e8749205b7a106f888cd2903d19461e24a7697 \ + --hash=sha256:3b7fe075e91b9d9cff40eba4fb6a8eff74964d3979a39be9a9ef58b1b4cb3604 \ + --hash=sha256:3bf4b5bae472630c229518e4a814b1b68f10a3d9b00aeaec45f1a330f03a0251 \ + --hash=sha256:3f006c28c885deb99b670a5a66f367a175ab8955b0374029bad7111f5357dcd4 \ + --hash=sha256:3f5446068197b35a11ccc697720c41879c8657e2e761aaa8311783aac84cef20 \ + --hash=sha256:3fa6811a618653164f918b891a0fa07052bd71a799defa5c44d167cac5557b26 \ + --hash=sha256:46525fbd84523cac75af5bf524bc74aaac848beaf31b142d2df8a787d9b4bbc4 \ + --hash=sha256:477c34c4489666dc73cb5e89dafe2617c3e13da1298917f73d55aac4696bd793 \ + --hash=sha256:4b3e974ad15eb32b1f537730dea70b93a4c3db7b026de3ad2b59da49c6f7454d \ + --hash=sha256:4c3b8be557e08b234774925622e196f0ee36fe4eab66cd19df934d3efd8f3743 \ + --hash=sha256:4e3e3e31423f888d396b1fc1f936936e52af868ac1ec17dd15e3eeba9dd4de24 \ + --hash=sha256:4e43e2b5acaad09cf48c032f7e4926392bb3a3f01854416cf6d82ebff94d5467 \ + --hash=sha256:4ed68a3b1ccb4313d2a42546fd7e7439ad4745918a48b6c9bcaa61e1e3e42634 \ + --hash=sha256:4f674e309cd055ee7a48304ceb8cf43265d859faf4d7d01d270ce45e976ae9d3 \ + --hash=sha256:50171f985e17970f87d5a29e16603d1e5b03bdbf5c2691a37e6c912942a6b657 \ + --hash=sha256:51341e70b467004dcbec3a6ce8c478d2d6241e0f6b01e4c56764afd5022e1e9d \ + --hash=sha256:5a4bcef114fc071d5f52c386c47f35aae0a5b43673197b9288a15b584da8fa3a \ + --hash=sha256:5a5c8019ff94988d56eb49b15de76fe83f6b42536d76edeb6565dbf7fe14b973 \ + --hash=sha256:5cda592405bbd29d53942e0389dc3fa77b49c362640210d7e94a10c14a677d4d \ + --hash=sha256:5e6674a017629284ef373b50496d9fb1a89b85a20a7fa100ecd109484ec748e5 \ + --hash=sha256:5e7bb4dd524f50b71c20ef5a12bd61da9b463f8894b18a06130942fe31509881 \ + --hash=sha256:60c4e3c258eafaab21b174b17270a0cc093718d61cdbde8c03f85ec4bf835343 \ + --hash=sha256:61995eb826009d99ed8590747bc0da683a5f4fbb4faa8788166bf3810845cd5c \ + --hash=sha256:61a72e4a523cdfc521762137559c08dfa360a3caef63620be58c699d1717dac1 \ + --hash=sha256:69536b821dd1bc78058a6e7541743f8d82bf2d981b91280b14c4daa6cdc7faba \ + --hash=sha256:6ccdcb635dae85b006592f78e32d97f4bc7541cb27829d505f9c7fefcef48298 \ + --hash=sha256:6f88cafe46612b6fa68e6dea49e25bebf160598bba00101caa51cc8c1f18d597 \ + --hash=sha256:6f969edc851efe23010e0f53a64269f2629a9364135e9ec81c842e8b2277d0c1 \ + --hash=sha256:77924b0d32fd1f493d3df15d9609ddf9d94c31a364022a6bf6b525ce9da75bea \ + --hash=sha256:7df645b6b7800e8b748c217fbd6a4ca8361bcb9a1ae6206cc02377833ec8a1aa \ + --hash=sha256:7e17d04ea58ab8cf3f2dc52e875db16077c6357846006780086fff3189fb199d \ + --hash=sha256:7f2b34a6444b8f9c1e9f84bd2c639388e5d14f128afd14a869dfb3d9af893aa2 \ + --hash=sha256:818dfd310aa1020a13cd08ee48e116dd8c3bb2e23b8161f8ac4df587dd5093d7 \ + --hash=sha256:89a258424158eb8b3ed9f65548d68998da334ef155d09488c5637723eb1cd697 \ + --hash=sha256:8eceffca3941775b646cd585cd19b275d382de43cc3327d22f7c75d7b003d481 \ + --hash=sha256:8f280ab4e043b089777b43b4227bdc2035f88da5072ab36588e0ccf77d45d058 \ + --hash=sha256:8f9dbe12f011a9b784f58faecc171d22465bb532c310bd588d769ba79a59ef5a \ + --hash=sha256:9076ce8429785c85f824650735791738de7143f61f43ae9ed83e163c0ca0fa44 \ + --hash=sha256:95d2305fd2a7b179cacb48b10f618872fc565c175f9f62b854e8d1acac3e8a9e \ + --hash=sha256:96d9ea6c8d4cbdeee2e0d43379ce2881e4af0454b00570677c59f33f2531cd38 \ + --hash=sha256:9944a2cac25ffe049a7e89f306e11b900640837d1ef38d9be0eaa4a4e2b73a52 \ + --hash=sha256:9a1a80a8fa767f2fdc3870316a54b84fe9fc09fa6ab6a2686783de6a228a4604 \ + --hash=sha256:9cd32326dfa6ce87edf754153b0105aca64486bebe93b9600ccff74fa0b224df \ + --hash=sha256:9f4a65276f6ecdebe75f2a53f578fbc40e8d2860658420d5e0611c56bbf5054c \ + --hash=sha256:a286ded34eb16501002e3713b3130c987366eee2ba0d58c33c72f27778e31676 \ + --hash=sha256:a2df98f5e071320c7d84e8bd07c0542acdd0a7519307fc31774d60e4b842ec4f \ + --hash=sha256:a7205497d7276a81fe92951a29616ef96562ed2f91a02066f72b6f93cb34b40e \ + --hash=sha256:aa17a3b22b3726d54d7af20394f65d4a1735a842a4e0f557dc67a90f6965c4bc \ + --hash=sha256:af33f370be90b48bbaf0dab32decbdcc522b1fa95d109020a963282086518a8e \ + --hash=sha256:b17baf702c6e5b4bb66e1281a3efbb1d749c9d06cdb92b665ad81e03118f78fc \ + --hash=sha256:b4f3d06dc16671b88a13ae85d8ca92534c0b637d59e49f0558d040a691246422 \ + --hash=sha256:b9953d87418ac228f508d93898ab572775e4d3b0eeb886a1a7734553bcdaf291 \ + --hash=sha256:b9a7c987e161e3c58f992c63b7e26fea7fe0777f3b975799d23d65bbb8cb5899 \ + --hash=sha256:c6cb613148422c523945cdb8b6bed617856f2602fd8750e33773ede2616e55d5 \ + --hash=sha256:c9b9e5bde7030cae83aa900b5bd660decc65afd2db8c400f3c568c815a47ca2a \ + --hash=sha256:cc36a9dded458d4e37492fe3e619c6c83caae794d26ad925adbce61d592f8428 \ + --hash=sha256:cd2614f17e261f72efc2f19f5e5ff2ee19e2296570c0dcf33409e22be30710de \ + --hash=sha256:d115790f18daa99b5c11a506e48923b630ef712e9e4b40482af942c3d40638b8 \ + --hash=sha256:d194decd9608f11c777946f596f31d5aacad13972a0a87829ae1e6f2d26c1885 \ + --hash=sha256:d1a4ce40ba11da9382c14da31f4f9e88c18f7d294f523decd0fadfb81f51ad18 \ + --hash=sha256:d1be9e30e675f5bc1cb534633324578f6f0944a1bcffe53242cf632f554f83b6 \ + --hash=sha256:d20891e3f33803b26d54c77fd5745878497091e33f4bbbdd454cf6e71aee8890 \ + --hash=sha256:d27e560eefb57914d742a837f1da98d3b29cb22eff013c8023b7cf52ae6e051d \ + --hash=sha256:dcb0569dd5bfe6004658cd0f229efa699a3169dcb4f77bd72e188adda302063d \ + --hash=sha256:e62ec131816c6120eff40dffe43424e140264a15fa4ab88c301bd6a595913af3 \ + --hash=sha256:e75163773a309e56a9b58165cf5a50e0f84b755f6ff863b2c01a38918fe92daa \ + --hash=sha256:ec58fb7c2062f835595c12f0f02dcda76d0eb0831423cc191d1e18c9276648de \ + --hash=sha256:f1eadbcd3de55ac42310ff82550d3302cb4efcd4e17d76646a17b6e7004bb42b \ + --hash=sha256:f2dcb8389fa3d453927b1299f46bdb38473c293c8269d5c777d33ea0e526b610 \ + --hash=sha256:ffaf841546905d90ff189de7397aa56413b1ce5e54547f17a98f0ebf3a3b0a3b + # via redis httpcore==0.17.2 \ --hash=sha256:125f8375ab60036db632f34f4b627a9ad085048eef7cb7d2616fea0f739f98af \ --hash=sha256:5581b9c12379c4288fe70f43c710d16060c10080617001e6b22a3b6dbcbefd36 @@ -407,7 +503,13 @@ pyyaml==6.0 \ # via # -r requirements/main.in # uvicorn -safir==4.3.0 \ +redis[hiredis]==4.6.0 \ + --hash=sha256:585dc516b9eb042a619ef0a39c3d7d55fe81bdb4df09a52c9cdde0d07bf1aa7d \ + --hash=sha256:e2b03db868160ee4591de3cb90d40ebb50a90dd302138775937f6a42b7ed183c + # via + # arq + # safir +safir[arq,redis]==4.3.0 \ --hash=sha256:7a5df1d6a2dd22aa8ba8d19e3390721152fe43540e7dbb754dac321affe8dc43 \ --hash=sha256:ce4f3d8ff34a9044650e07bdf2214d1462fc49a07d7ac864e2232433d6630fbe # via -r requirements/main.in @@ -422,48 +524,48 @@ sniffio==1.3.0 \ # anyio # httpcore # httpx -sqlalchemy==2.0.16 \ - --hash=sha256:0db6734cb5644c55d0262a813b764c6e2cda1e66e939a488b3d6298cdc7344c2 \ - --hash=sha256:0e4645b260cfe375a0603aa117f0a47680864cf37833129da870919e88b08d8f \ - --hash=sha256:131f0c894c6572cb1bdcf97c92d999d3128c4ff1ca13061296057072f61afe13 \ - --hash=sha256:1e2caba78e7d1f5003e88817b7a1754d4e58f4a8f956dc423bf8e304c568ab09 \ - --hash=sha256:2de1477af7f48c633b8ecb88245aedd811dca88e88aee9e9d787b388abe74c44 \ - --hash=sha256:2f3b6c31b915159b96b68372212fa77f69230b0a32acab40cf539d2823954f5a \ - --hash=sha256:3ef876615ff4b53e2033022195830ec4941a6e21068611f8d77de60203b90a98 \ - --hash=sha256:43e69c8c1cea0188b7094e22fb93ae1a1890aac748628b7e925024a206f75368 \ - --hash=sha256:53081c6fce0d49bb36d05f12dc87e008c9b0df58a163b792c5fc4ac638925f98 \ - --hash=sha256:5a934eff1a2882137be3384826f997db8441d43b61fda3094923e69fffe474be \ - --hash=sha256:5e8522b49e0e640287308b68f71cc338446bbe1c226c8f81743baa91b0246e92 \ - --hash=sha256:61f2035dea56ff1a429077e481496f813378beb02b823d2e3e7eb05bc1a7a8ca \ - --hash=sha256:63ea36c08792a7a8a08958bc806ecff6b491386feeaf14607c3d9d2d9325e67f \ - --hash=sha256:6e85e315725807c127ad8ba3d628fdb861cf9ebfb0e10c39a97c01e257cdd71b \ - --hash=sha256:7641f6ed2682de84d77c4894cf2e43700f3cf7a729361d7f9cac98febf3d8614 \ - --hash=sha256:7be04dbe3470fe8dd332fdb48c979887c381ef6c635eddf2dec43d2766111be4 \ - --hash=sha256:81d867c1be5abd49f7e547c108391f371a9d980ba7ec34666c50d683f782b754 \ - --hash=sha256:8544c6e62eacb77d5106e2055ef10f2407fc0dbd547e879f8745b2032eefd2bc \ - --hash=sha256:8d3cbdb2f07fb0e4b897dc1df39166735e194fb946f28f26f4c9f9801c8b24f7 \ - --hash=sha256:8d6ef848e5afcd1bda3e9a843751f845c0ca888b61e669237680e913d84ec206 \ - --hash=sha256:8e2569dac4e3cb85365b91ab569d06a221e0e17e65ce59949d00c3958946282b \ - --hash=sha256:90d320fde566b864adbc19abb40ecb80f4e25d6f084639969bb972d5cca16858 \ - --hash=sha256:91eb8f89fcce8f709f8a4d65d265bc48a80264ee14c7c9e955f3222f19b4b39c \ - --hash=sha256:a08a791c75d6154d46914d1e23bd81d9455f2950ec1de81f2723848c593d2c8b \ - --hash=sha256:a2e9f50a906d0b81292576a9fb458f8cace904c81a67088f4a2ca9ff2856f55d \ - --hash=sha256:a5a2856e12cf5f54301ddf043bcbf0552561d61555e1bcf348b63f42b8e1eec2 \ - --hash=sha256:b2801f85c5c0293aa710f8aa5262c707a83c1c203962ae5a22b4d9095e71aa9d \ - --hash=sha256:b72f4e4def50414164a1d899f2ce4e782a029fad0ed5585981d1611e8ae29a74 \ - --hash=sha256:bdaf89dd82f4a0e1b8b5ffc9cdc0c9551be6175f7eee5af6a838e92ba2e57100 \ - --hash=sha256:c5e333b81fe10d14efebd4e9429b7bb865ed9463ca8bef07a7136dfa1fd4a37b \ - --hash=sha256:ce1fc3f64fd42d5f763d6b83651471f32920338a1ba107a3186211474861af57 \ - --hash=sha256:d0c96592f54edd571e00ba6b1ed5df8263328ca1da9e78088c0ebc93c2e6562c \ - --hash=sha256:dc97238fa44be86971270943a0c21c19ce18b8d1596919048e57912e8abc02cc \ - --hash=sha256:e19546924f0cf2ec930d1faf318b7365e5827276410a513340f31a2b423e96a4 \ - --hash=sha256:f2938edc512dd1fa48653e14c1655ab46144d4450f0e6b33da7acd8ba77fbfd7 \ - --hash=sha256:f387b496a4c9474d8580195bb2660264a3f295a04d3a9d00f4fa15e9e597427e \ - --hash=sha256:f409f35a0330ab0cb18ece736b86d8b8233c64f4461fcb10993f67afc0ac7e5a \ - --hash=sha256:f662cf69484c59f8a3435902c40dfc34d86050bdb15e23d437074ce9f153306b \ - --hash=sha256:fbcc51fdbc89fafe4f4fe66f59372a8be88ded04de34ef438ab04f980beb12d4 \ - --hash=sha256:fc1dae11bd5167f9eb53b3ccad24a79813004612141e76de21cf4c028dc30b34 \ - --hash=sha256:ff6496ad5e9dc8baeb93a151cc2f599d01e5f8928a2aaf0b09a06428fdbaf553 +sqlalchemy==2.0.17 \ + --hash=sha256:04383f1e3452f6739084184e427e9d5cb4e68ddc765d52157bf5ef30d5eca14f \ + --hash=sha256:125f9f7e62ddf8b590c069729080ffe18b68a20d9882eb0947f72e06274601d7 \ + --hash=sha256:1822620c89779b85f7c23d535c8e04b79c517739ae07aaed48c81e591ed5498e \ + --hash=sha256:21583808d37f126a647652c90332ac1d3a102edf3c94bcc3319edcc0ea2300cc \ + --hash=sha256:218fb20c01e95004f50a3062bf4c447dcb360cab8274232f31947e254f118298 \ + --hash=sha256:2269b1f9b8be47e52b70936069a25a3771eff53367aa5cc59bb94f28a6412e13 \ + --hash=sha256:234678ed6576531b8e4be255b980f20368bf07241a2e67b84e6b0fe679edb9c4 \ + --hash=sha256:28da17059ecde53e2d10ba813d38db942b9f6344360b2958b25872d5cb729d35 \ + --hash=sha256:2c6ff5767d954f6091113fedcaaf49cdec2197ae4c5301fe83d5ae4393c82f33 \ + --hash=sha256:36a87e26fe8fa8c466fae461a8fcb780d0a1cbf8206900759fc6fe874475a3ce \ + --hash=sha256:394ac3adf3676fad76d4b8fcecddf747627f17f0738dc94bac15f303d05b03d4 \ + --hash=sha256:40a3dc52b2b16f08b5c16b9ee7646329e4b3411e9280e5e8d57b19eaa51cbef4 \ + --hash=sha256:48111d56afea5699bab72c38ec95561796b81befff9e13d1dd5ce251ab25f51d \ + --hash=sha256:48b40dc2895841ea89d89df9eb3ac69e2950a659db20a369acf4259f68e6dc1f \ + --hash=sha256:513411d73503a6fc5804f01fae3b3d44f267c1b3a06cfeac02e9286a7330e857 \ + --hash=sha256:51736cfb607cf4e8fafb693906f9bc4e5ee55be0b096d44bd7f20cd8489b8571 \ + --hash=sha256:5f40e3a7d0a464f1c8593f2991e5520b2f5b26da24e88000bbd4423f86103d4f \ + --hash=sha256:6150560fcffc6aee5ec9a97419ac768c7a9f56baf7a7eb59cb4b1b6a4d463ad9 \ + --hash=sha256:724355973297bbe547f3eb98b46ade65a67a3d5a6303f17ab59a2dc6fb938943 \ + --hash=sha256:74ddcafb6488f382854a7da851c404c394be3729bb3d91b02ad86c5458140eff \ + --hash=sha256:7830e01b02d440c27f2a5be68296e74ccb55e6a5b5962ffafd360b98930b2e5e \ + --hash=sha256:7f31d4e7ca1dd8ca5a27fd5eaa0f9e2732fe769ff7dd35bf7bba179597e4df07 \ + --hash=sha256:8741d3d401383e54b2aada37cbd10f55c5d444b360eae3a82f74a2be568a7710 \ + --hash=sha256:910d45bf3673f0e4ef13858674bd23cfdafdc8368b45b948bf511797dbbb401d \ + --hash=sha256:aa995b21f853864996e4056d9fde479bcecf8b7bff4beb3555eebbbba815f35d \ + --hash=sha256:af7e2ba75bf84b64adb331918188dda634689a2abb151bc1a583e488363fd2f8 \ + --hash=sha256:b0eaf82cc844f6b46defe15ad243ea00d1e39ed3859df61130c263dc7204da6e \ + --hash=sha256:b114a16bc03dfe20b625062e456affd7b9938286e05a3f904a025b9aacc29dd4 \ + --hash=sha256:b47be4c6281a86670ea5cfbbbe6c3a65366a8742f5bc8b986f790533c60b5ddb \ + --hash=sha256:ba03518e64d86f000dc24ab3d3a1aa876bcbaa8aa15662ac2df5e81537fa3394 \ + --hash=sha256:cc9c2630c423ac4973492821b2969f5fe99d9736f3025da670095668fbfcd4d5 \ + --hash=sha256:cf07ff9920cb3ca9d73525dfd4f36ddf9e1a83734ea8b4f724edfd9a2c6e82d9 \ + --hash=sha256:cf175d26f6787cce30fe6c04303ca0aeeb0ad40eeb22e3391f24b32ec432a1e1 \ + --hash=sha256:d0aeb3afaa19f187a70fa592fbe3c20a056b57662691fd3abf60f016aa5c1848 \ + --hash=sha256:e186e9e95fb5d993b075c33fe4f38a22105f7ce11cecb5c17b5618181e356702 \ + --hash=sha256:e2d5c3596254cf1a96474b98e7ce20041c74c008b0f101c1cb4f8261cb77c6d3 \ + --hash=sha256:e3189432db2f5753b4fde1aa90a61c69976f4e7e31d1cf4611bfe3514ed07478 \ + --hash=sha256:e3a6b2788f193756076061626679c5c5a6d600ddf8324f986bc72004c3e9d92e \ + --hash=sha256:ead58cae2a089eee1b0569060999cb5f2b2462109498a0937cc230a7556945a1 \ + --hash=sha256:f2f389f77c68dc22cb51f026619291c4a38aeb4b7ecb5f998fd145b2d81ca513 \ + --hash=sha256:f593170fc09c5abb1205a738290b39532f7380094dc151805009a07ae0e85330 # via fastapi-sqlalchemy starlette==0.27.0 \ --hash=sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75 \ @@ -479,10 +581,11 @@ structlog==23.1.0 \ # via # -r requirements/main.in # safir -typing-extensions==4.6.3 \ - --hash=sha256:88a4153d8505aabbb4e13aacb7c486c2b4a33ca3b3f807914a9b4c844c471c26 \ - --hash=sha256:d91d5919357fe7f681a9f2b5b4cb2a5f1ef0a1e9f59c4d8ff0d3491e05c0ffd5 +typing-extensions==4.7.0 \ + --hash=sha256:5d8c9dac95c27d20df12fb1d97b9793ab8b2af8a3a525e68c80e21060c161771 \ + --hash=sha256:935ccf31549830cda708b42289d44b6f74084d616a00be651601a4f968e77c82 # via + # arq # pydantic # sqlalchemy uc-micro-py==1.0.2 \ diff --git a/src/semaphore/config.py b/src/semaphore/config.py index 1a19e06..201c836 100644 --- a/src/semaphore/config.py +++ b/src/semaphore/config.py @@ -11,8 +11,11 @@ from enum import Enum from typing import Any, Mapping, Optional +from urllib.parse import urlparse -from pydantic import BaseSettings, Field, SecretStr, validator +from arq.connections import RedisSettings +from pydantic import BaseSettings, Field, RedisDsn, SecretStr, validator +from safir.arq import ArqMode # from safir.logging import configure_logging @@ -84,6 +87,29 @@ class Config(BaseSettings): For a list of environments, see https://github.com/lsst-sqre/phalanx. """ + slack_webhook_url: Optional[SecretStr] = Field( + None, env="SEMAPHORE_SLACK_PRIVATE_KEY" + ) + """The Slack app private key.""" + + redis_url: RedisDsn = Field( + env="SEMAPHORE_REDIS_URL", + default_factory=lambda: RedisDsn( + "redis://localhost:6379/0", scheme="redis" + ), + ) + """URL for the redis instance, used by the worker queue.""" + + redis_queue_url: RedisDsn = Field( + env="SEMAPHORE_REDIS_URL", + default_factory=lambda: RedisDsn( + "redis://localhost:6379/0", scheme="redis" + ), + ) + """URL for the redis instance, used by the arq queue.""" + + arq_mode: ArqMode = Field(ArqMode.production, env="SEMAPHORE_ARQ_MODE") + @validator("github_webhook_secret", "github_app_private_key", pre=True) def validate_none_secret( cls, v: Optional[SecretStr] @@ -123,5 +149,16 @@ def validate_github_app(cls, v: bool, values: Mapping[str, Any]) -> bool: return True + @property + def arq_redis_settings(self) -> RedisSettings: + """Create a Redis settings instance for arq.""" + url_parts = urlparse(self.redis_queue_url) + redis_settings = RedisSettings( + host=url_parts.hostname or "localhost", + port=url_parts.port or 6379, + database=int(url_parts.path.lstrip("/")) if url_parts.path else 0, + ) + return redis_settings + config = Config() diff --git a/src/semaphore/dependencies/redis.py b/src/semaphore/dependencies/redis.py new file mode 100644 index 0000000..6d5c6d4 --- /dev/null +++ b/src/semaphore/dependencies/redis.py @@ -0,0 +1,44 @@ +"""Redis dependency for FastAPI.""" + +from typing import Optional + +from redis.asyncio import Redis + +__all__ = ["RedisDependency", "redis_dependency"] + + +class RedisDependency: + """Provides an asyncio-based Redis client as a dependency. + Notes + ----- + This dependency must be initialized in a start-up hook (`initialize`) and + closed in a shut down hook (`close`). + """ + + def __init__(self) -> None: + self.redis: Redis | None = None + + async def initialize( + self, redis_url: str, password: Optional[str] = None + ) -> None: + self.redis = Redis.from_url(redis_url, password=password) + + async def __call__(self) -> Redis: + """Returns the redis pool.""" + if self.redis is None: + raise RuntimeError("RedisDependency is not initialized") + return self.redis + + async def close(self) -> None: + """Close the open Redis pool. + Should be called from a shutdown hook to ensure that the Redis clients + are cleanly shut down and any pending writes are complete. + """ + if self.redis: + await self.redis.close() + await self.redis.connection_pool.disconnect() + self.redis = None + + +redis_dependency = RedisDependency() +"""The dependency that will return the Redis pool.""" diff --git a/src/semaphore/main.py b/src/semaphore/main.py index bd58f4d..e356d0f 100644 --- a/src/semaphore/main.py +++ b/src/semaphore/main.py @@ -9,12 +9,14 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.utils import get_openapi +from safir.dependencies.arq import arq_dependency from safir.dependencies.http_client import http_client_dependency from safir.logging import configure_logging from safir.middleware.x_forwarded import XForwardedMiddleware from .config import config from .dependencies.broadcastrepo import broadcast_repo_dependency +from .dependencies.redis import redis_dependency from .github.broadcastservices import bootstrap_broadcast_repo from .handlers.external import external_router from .handlers.internal import internal_router @@ -64,6 +66,11 @@ async def startup_event() -> None: logger = structlog.get_logger(config.logger_name) logger.info("Running startup") + await redis_dependency.initialize(config.redis_url) + await arq_dependency.initialize( + mode=config.arq_mode, redis_settings=config.arq_redis_settings + ) + broadcast_repo = await broadcast_repo_dependency() if config.enable_github_app: await bootstrap_broadcast_repo( @@ -76,6 +83,7 @@ async def startup_event() -> None: @app.on_event("shutdown") async def shutdown_event() -> None: await http_client_dependency.aclose() + await redis_dependency.close() def create_openapi() -> str: diff --git a/src/semaphore/worker/__init__.py b/src/semaphore/worker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/semaphore/worker/functions/__init__.py b/src/semaphore/worker/functions/__init__.py new file mode 100644 index 0000000..8b63a6a --- /dev/null +++ b/src/semaphore/worker/functions/__init__.py @@ -0,0 +1,5 @@ +from .ping import ping + +__all__ = [ + "ping", +] diff --git a/src/semaphore/worker/functions/ping.py b/src/semaphore/worker/functions/ping.py new file mode 100644 index 0000000..7cb4fd8 --- /dev/null +++ b/src/semaphore/worker/functions/ping.py @@ -0,0 +1,11 @@ +"""A proof-of-concept worker function.""" + +from __future__ import annotations + +from typing import Any, Dict + + +async def ping(ctx: Dict[Any, Any]) -> str: + logger = ctx["logger"].bind(task="ping") + logger.info("Running ping") + return "pong" diff --git a/src/semaphore/worker/functions/send_message.py b/src/semaphore/worker/functions/send_message.py new file mode 100644 index 0000000..e69de29 diff --git a/src/semaphore/worker/main.py b/src/semaphore/worker/main.py new file mode 100644 index 0000000..d4a0ae5 --- /dev/null +++ b/src/semaphore/worker/main.py @@ -0,0 +1,71 @@ +"""Arq-based queue worker lifecycle configuration.""" + +from __future__ import annotations + +import uuid +from typing import Any, Dict + +import httpx +import structlog +from safir.logging import configure_logging + +from semaphore.config import config +from semaphore.dependencies.redis import redis_dependency + +from .functions import ping + + +async def startup(ctx: Dict[Any, Any]) -> None: + """Runs during working start-up to set up the worker context.""" + configure_logging( + profile=config.profile, + log_level=config.log_level, + name="semaphore", + ) + logger = structlog.get_logger("semaphore") + # The instance key uniquely identifies this worker in logs + instance_key = uuid.uuid4().hex + logger = logger.bind(worker_instance=instance_key) + + logger.info("Starting up worker") + + http_client = httpx.AsyncClient() + ctx["http_client"] = http_client + + ctx["logger"] = logger + logger.info("Start up complete") + await redis_dependency.initialize(config.redis_url) + + +async def shutdown(ctx: Dict[Any, Any]) -> None: + """Runs during worker shut-down to resources.""" + if "logger" in ctx.keys(): + logger = ctx["logger"] + else: + logger = structlog.get_logger(__name__) + logger.info("Running worker shutdown.") + + await redis_dependency.close() + + try: + await ctx["http_client"].aclose() + except Exception as e: + logger.warning("Issue closing the http_client: %s", str(e)) + + logger.info("Worker shutdown complete.") + + +class WorkerSettings: + """Configuration for a Times Square arq worker. + See `arq.worker.Worker` for details on these attributes. + """ + + functions = [ + ping, + ] + + redis_settings = config.arq_redis_settings + + on_startup = startup + + on_shutdown = shutdown diff --git a/tox.ini b/tox.ini index c491699..33a0c8e 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,19 @@ envlist = py,typing,lint,docs,coverage-report isolated_build = True +[docker:redis] +image = redis:latest +ports = + 6379:6379/tcp +healthcheck_cmd = + redis-cli ping +healthcheck_timeout = 1 +healthcheck_retries = 30 +healthcheck_interval = 1 +healthcheck_start_period = 1 + [testenv] -description = Run pytest. +description = Environment with test dependencies. deps = -r{toxinidir}/requirements/main.txt -r{toxinidir}/requirements/dev.txt @@ -15,6 +26,12 @@ setenv = commands = pytest --cov=semaphore --cov-branch --cov-report= {posargs} +[testenv:docker] +description = Run pytest with PostgreSQL via Docker. +docker = + postgres + redis + [testenv:coverage-report] description = Compile coverage from each test run. skip_install = true