We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Extend RConn to be able to connect to different Redis servers from within the same web2py application
Right now it's not possible to connect to different Redis servers from within the same web2py application. Taking a look at the [code of RConn class](https://github.com/web2py/web2py/blob/f06c60b963a373f661e3bb09d5af49d2098902ec/gluon/contrib/redis_utils.py#L39), you can see that the first stablished connection made to a Redis server is linked to the current web2py application. And subsequent calls to RConn from within that web2py application will return the first created connection, no matter what the connection parameters are.

This is a problem if you need to connect to different Redis servers from within the same web2py application. Notice this is also a problem if some of the connection arguments change (host, port, password, etc). 

I'm not shure what's the reason for returning always the first stablished connection, but I think a couple of fixes could be done in order to avoid this issues. I'll prepare a pull request with a proposal. 


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gluon/contrib/redis_utils.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 Developed by niphlod@gmail.com
5 License MIT/BSD/GPL
6 
7 Serves as base to implement Redis connection object and various utils
8 for redis_cache, redis_session and redis_scheduler in the future
9 Should-could be overriden in case redis doesn't keep up (e.g. cluster support)
10 to ensure compatibility with another - similar - library
11 """
12 
13 import logging
14 from threading import Lock
15 import time
16 from gluon import current
17 
18 logger = logging.getLogger("web2py.redis_utils")
19 
20 try:
21     import redis
22     from redis.exceptions import WatchError as RWatchError
23     from redis.exceptions import ConnectionError as RConnectionError
24 except ImportError:
25     logger.error("Needs redis library to work")
26     raise RuntimeError('Needs redis library to work')
27 
28 
29 locker = Lock()
30 
31 
32 def RConn(*args, **vars):
33     """
34     Istantiates a StrictRedis connection with parameters, at the first time
35     only
36     """
37     locker.acquire()
38     try:
39         instance_name = 'redis_conn_' + current.request.application
40         if not hasattr(RConn, instance_name):
41             setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))
42         return getattr(RConn, instance_name)
43     finally:
44         locker.release()
45 
46 def acquire_lock(conn, lockname, identifier, ltime=10):
47     while True:
48         if conn.set(lockname, identifier, ex=ltime, nx=True):
49             return identifier
50         time.sleep(.01)
51 
52 
53 _LUA_RELEASE_LOCK = """
54 if redis.call("get", KEYS[1]) == ARGV[1]
55 then
56     return redis.call("del", KEYS[1])
57 else
58     return 0
59 end
60 """
61 
62 
63 def release_lock(instance, lockname, identifier):
64     return instance._release_script(
65         keys=[lockname], args=[identifier])
66 
67 
68 def register_release_lock(conn):
69     rtn = conn.register_script(_LUA_RELEASE_LOCK)
70     return rtn
71
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gluon/contrib/redis_utils.py b/gluon/contrib/redis_utils.py
--- a/gluon/contrib/redis_utils.py
+++ b/gluon/contrib/redis_utils.py
@@ -29,14 +29,16 @@
 locker = Lock()
 
 
-def RConn(*args, **vars):
+def RConn(application=None, *args, **vars):
     """
     Istantiates a StrictRedis connection with parameters, at the first time
     only
     """
     locker.acquire()
     try:
-        instance_name = 'redis_conn_' + current.request.application
+        if application is None:
+            application = current.request.application
+        instance_name = 'redis_conn_' + application
         if not hasattr(RConn, instance_name):
             setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))
         return getattr(RConn, instance_name)

{"golden_diff": "diff --git a/gluon/contrib/redis_utils.py b/gluon/contrib/redis_utils.py\n--- a/gluon/contrib/redis_utils.py\n+++ b/gluon/contrib/redis_utils.py\n@@ -29,14 +29,16 @@\n locker = Lock()\n \n \n-def RConn(*args, **vars):\n+def RConn(application=None, *args, **vars):\n     \"\"\"\n     Istantiates a StrictRedis connection with parameters, at the first time\n     only\n     \"\"\"\n     locker.acquire()\n     try:\n-        instance_name = 'redis_conn_' + current.request.application\n+        if application is None:\n+            application = current.request.application\n+        instance_name = 'redis_conn_' + application\n         if not hasattr(RConn, instance_name):\n             setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))\n         return getattr(RConn, instance_name)\n", "issue": "Extend RConn to be able to connect to different Redis servers from within the same web2py application\nRight now it's not possible to connect to different Redis servers from within the same web2py application. Taking a look at the [code of RConn class](https://github.com/web2py/web2py/blob/f06c60b963a373f661e3bb09d5af49d2098902ec/gluon/contrib/redis_utils.py#L39), you can see that the first stablished connection made to a Redis server is linked to the current web2py application. And subsequent calls to RConn from within that web2py application will return the first created connection, no matter what the connection parameters are.\r\n\r\nThis is a problem if you need to connect to different Redis servers from within the same web2py application. Notice this is also a problem if some of the connection arguments change (host, port, password, etc). \r\n\r\nI'm not shure what's the reason for returning always the first stablished connection, but I think a couple of fixes could be done in order to avoid this issues. I'll prepare a pull request with a proposal. \r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\nDeveloped by niphlod@gmail.com\nLicense MIT/BSD/GPL\n\nServes as base to implement Redis connection object and various utils\nfor redis_cache, redis_session and redis_scheduler in the future\nShould-could be overriden in case redis doesn't keep up (e.g. cluster support)\nto ensure compatibility with another - similar - library\n\"\"\"\n\nimport logging\nfrom threading import Lock\nimport time\nfrom gluon import current\n\nlogger = logging.getLogger(\"web2py.redis_utils\")\n\ntry:\n    import redis\n    from redis.exceptions import WatchError as RWatchError\n    from redis.exceptions import ConnectionError as RConnectionError\nexcept ImportError:\n    logger.error(\"Needs redis library to work\")\n    raise RuntimeError('Needs redis library to work')\n\n\nlocker = Lock()\n\n\ndef RConn(*args, **vars):\n    \"\"\"\n    Istantiates a StrictRedis connection with parameters, at the first time\n    only\n    \"\"\"\n    locker.acquire()\n    try:\n        instance_name = 'redis_conn_' + current.request.application\n        if not hasattr(RConn, instance_name):\n            setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))\n        return getattr(RConn, instance_name)\n    finally:\n        locker.release()\n\ndef acquire_lock(conn, lockname, identifier, ltime=10):\n    while True:\n        if conn.set(lockname, identifier, ex=ltime, nx=True):\n            return identifier\n        time.sleep(.01)\n\n\n_LUA_RELEASE_LOCK = \"\"\"\nif redis.call(\"get\", KEYS[1]) == ARGV[1]\nthen\n    return redis.call(\"del\", KEYS[1])\nelse\n    return 0\nend\n\"\"\"\n\n\ndef release_lock(instance, lockname, identifier):\n    return instance._release_script(\n        keys=[lockname], args=[identifier])\n\n\ndef register_release_lock(conn):\n    rtn = conn.register_script(_LUA_RELEASE_LOCK)\n    return rtn\n", "path": "gluon/contrib/redis_utils.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\"\"\"\nDeveloped by niphlod@gmail.com\nLicense MIT/BSD/GPL\n\nServes as base to implement Redis connection object and various utils\nfor redis_cache, redis_session and redis_scheduler in the future\nShould-could be overriden in case redis doesn't keep up (e.g. cluster support)\nto ensure compatibility with another - similar - library\n\"\"\"\n\nimport logging\nfrom threading import Lock\nimport time\nfrom gluon import current\n\nlogger = logging.getLogger(\"web2py.redis_utils\")\n\ntry:\n    import redis\n    from redis.exceptions import WatchError as RWatchError\n    from redis.exceptions import ConnectionError as RConnectionError\nexcept ImportError:\n    logger.error(\"Needs redis library to work\")\n    raise RuntimeError('Needs redis library to work')\n\n\nlocker = Lock()\n\n\ndef RConn(application=None, *args, **vars):\n    \"\"\"\n    Istantiates a StrictRedis connection with parameters, at the first time\n    only\n    \"\"\"\n    locker.acquire()\n    try:\n        if application is None:\n            application = current.request.application\n        instance_name = 'redis_conn_' + application\n        if not hasattr(RConn, instance_name):\n            setattr(RConn, instance_name, redis.StrictRedis(*args, **vars))\n        return getattr(RConn, instance_name)\n    finally:\n        locker.release()\n\ndef acquire_lock(conn, lockname, identifier, ltime=10):\n    while True:\n        if conn.set(lockname, identifier, ex=ltime, nx=True):\n            return identifier\n        time.sleep(.01)\n\n\n_LUA_RELEASE_LOCK = \"\"\"\nif redis.call(\"get\", KEYS[1]) == ARGV[1]\nthen\n    return redis.call(\"del\", KEYS[1])\nelse\n    return 0\nend\n\"\"\"\n\n\ndef release_lock(instance, lockname, identifier):\n    return instance._release_script(\n        keys=[lockname], args=[identifier])\n\n\ndef register_release_lock(conn):\n    rtn = conn.register_script(_LUA_RELEASE_LOCK)\n    return rtn\n", "path": "gluon/contrib/redis_utils.py"}]}