Repository: ethereum/web3.py

Issue:
Potential race condition when writing cache entries in simple_cache_middleware
* Version: 6.3.0
* Python: 3.10.1
* OS: osx

<details><summary>`pip freeze` output</summary>
<p>

```
aiohttp==3.8.4
aiosignal==1.3.1
alabaster==0.7.13
async-timeout==4.0.2
attrs==23.1.0
Babel==2.12.1
base58==2.1.1
bitarray==2.7.4
black==23.3.0
bleach==6.0.0
build==0.10.0
bump2version==1.0.1
bumpversion==0.6.0
cached-property==1.5.2
certifi==2023.5.7
charset-normalizer==3.1.0
click==8.1.3
click-default-group==1.2.2
colorama==0.4.6
cytoolz==0.12.1
distlib==0.3.6
docopt==0.6.2
docutils==0.18.1
eth-abi==4.0.0
eth-account==0.8.0
eth-bloom==2.0.0
eth-hash==0.5.1
eth-keyfile==0.6.1
eth-keys==0.4.0
eth-rlp==0.3.0
eth-tester==0.9.0b1
eth-typing==3.3.0
eth-utils==2.1.0
exceptiongroup==1.1.1
execnet==1.9.0
filelock==3.12.0
flake8==3.8.3
flaky==3.7.0
frozenlist==1.3.3
hexbytes==0.3.0
hypothesis==6.75.9
idna==3.4
imagesize==1.4.1
importlib-metadata==6.6.0
incremental==22.10.0
iniconfig==2.0.0
ipfshttpclient==0.8.0a2
isort==5.12.0
jaraco.classes==3.2.3
Jinja2==3.1.2
jsonschema==4.17.3
keyring==23.13.1
lru-dict==1.2.0
markdown-it-py==2.2.0
MarkupSafe==2.1.2
mccabe==0.6.1
mdurl==0.1.2
more-itertools==9.1.0
multiaddr==0.0.9
multidict==6.0.4
mypy==0.910
mypy-extensions==0.4.4
netaddr==0.8.0
packaging==23.1
parsimonious==0.9.0
pathspec==0.11.1
pkginfo==1.9.6
platformdirs==3.5.1
pluggy==0.13.1
protobuf==4.23.2
py==1.11.0
py-ecc==6.0.0
py-evm==0.7.0a2
py-geth==3.12.0
pycodestyle==2.6.0
pycryptodome==3.18.0
pyethash==0.1.27
pyflakes==2.2.0
Pygments==2.15.1
pyproject_hooks==1.0.0
pyrsistent==0.19.3
pytest==7.3.1
pytest-asyncio==0.21.0
pytest-mock==3.10.0
pytest-watch==4.2.0
pytest-xdist==3.3.1
readme-renderer==37.3
regex==2023.5.5
requests==2.31.0
requests-toolbelt==1.0.0
rfc3986==2.0.0
rich==13.4.1
rlp==3.0.0
safe-pysha3==1.0.4
semantic-version==2.10.0
six==1.16.0
snowballstemmer==2.2.0
sortedcontainers==2.4.0
Sphinx==6.2.1
sphinx-rtd-theme==1.2.1
sphinxcontrib-applehelp==1.0.4
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.1
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
toml==0.10.2
tomli==2.0.1
toolz==0.12.0
towncrier==21.9.0
tox==3.28.0
tqdm==4.65.0
trie==2.1.0
twine==4.0.2
types-protobuf==3.19.13
types-requests==2.31.0.1
types-setuptools==67.8.0.0
types-urllib3==1.26.25.13
typing_extensions==4.6.3
urllib3==2.0.2
varint==1.0.2
virtualenv==20.23.0
watchdog==3.0.0
-e git+ssh://git@github.com/ethereum/web3.py.git@1782f7d033aeb0aa2941b1d5fad950ddbec5b36e#egg=web3
webencodings==0.5.1
websockets==11.0.3
when-changed==0.3.0
yarl==1.9.2
zipp==3.15.0
```

</p>
</details> 




### What was wrong?

In `simple_cache_middleware`, current code tries to get the lock without blocking when writing cache entries, but doesn't verify whether it did get the lock: https://github.com/ethereum/web3.py/blob/955e10c49d81ff6627c23f2486407919edbd77e6/web3/middleware/cache.py#L106-L110

### How can it be fixed?

Just check if you did get the lock, and only write in that case. Commit with a suggested fix here: https://github.com/cygnusv/web3.py/commit/6c35544e3c50cb42f528f27b7268dbe8a5a17f87



Discussion:

Resolving patch:
diff --git a/web3/middleware/cache.py b/web3/middleware/cache.py
--- a/web3/middleware/cache.py
+++ b/web3/middleware/cache.py
@@ -103,11 +103,11 @@ def middleware(method: RPCEndpoint, params: Any) -> RPCResponse:
 
                 response = make_request(method, params)
                 if should_cache_fn(method, params, response):
-                    lock.acquire(blocking=False)
-                    try:
-                        cache.cache(cache_key, response)
-                    finally:
-                        lock.release()
+                    if lock.acquire(blocking=False):
+                        try:
+                            cache.cache(cache_key, response)
+                        finally:
+                            lock.release()
                 return response
             else:
                 return make_request(method, params)


Test patch: