Sanic v22.9.1
python: 3.9.15
packages: sanic-routing==22.8.0, sanic-ext==22.9.1
I defined the redis extension myself, and the code is as follows:
class RedisPlugin(Extension):
name = 'redis'
def startup(self, bootstrap) -> None:
if getattr(self.app.config, 'NACOS'):
self.app.before_server_start(self.set_redis_config)
if self.included():
self.app.after_server_start(self.create_pool)
self.app.before_server_stop(self.disconnect_pool)
self.app.on_response(self.close_before_response)
return super().startup(bootstrap)
@staticmethod
async def create_pool(app: Sanic):
"""服务启动后创建redis连接池,并进行redis依赖注入
Args:
app (Sanic): sanic app
"""
config = app.ctx.redis_config
if config.get('url'):
url = config.pop('url')
pool = redis.ConnectionPool.from_url(url)
config['connection_pool'] = pool
redis_instance = redis.Redis(
auto_close_connection_pool=False,
connection_pool=pool
)
else:
pool = redis.ConnectionPool.from_url(f"redis://:{config['password']}@{config['host']}:{config['port']}")
redis_instance = redis.Redis(
auto_close_connection_pool=False,
connection_pool=pool
)
redis_proxy = RedisPool(redis_instance)
app.ext.dependency(redis_proxy, 'redis')
app.ctx.redis_session_token = redis_session.set(redis_instance)
@staticmethod
async def disconnect_pool(app: Sanic):
"""应用关闭前强关所有连接
Args:
app (Sanic): sanic app
"""
await app.ctx.redis.connection_pool.disconnect()
@staticmethod
async def close_before_response(request: Request, response: HTTPResponse):
"""请求返回前关闭当此redis session
Args:
request (Request): sanic request
response (HTTPResponse): sanic response
"""
session_token = request.app.ctx.redis_session_token
redis_session.reset(session_token)
await request.app.ctx.redis.close()
@staticmethod
async def set_redis_config(app: Sanic):
"""支持nacos时,服务器端将redis配置信息写入配置中心
Args:
app (Sanic): sanic app
"""
nacos_client = NacosClient()
res = await nacos_client.get_config('redis', app.config.NACOS_GROUP, app.config.NACOS_NAMESPACE)
if res[0]:
config = res[0]
else:
config = get_local_redis_config(app)
app.ctx.redis_config = config
def included(self):
return self.app.config.CACHE_CONFIG
The dependency
method is used
app.ext.dependency(redis_proxy, 'redis')
I also saw the log on startup
[2022-12-03 16:23:19 +0800] [27159] [INFO] > redis
When you use a dependency object intended to use redis in an api method, you are prompted for missing keyword arguments
@openapi.definition(exclude=True)
async def post(self, request: Request, redis: RedisPool) -> HTTPResponse:
...
post() missing 1 required positional argument: 'redis'
I removed the redis argument and printed app.ctx.__dict__
,Found that ‘_dependencies’ already has a redis object but cannot be used
{'auth': <sanic_jwt.authentication.Authentication object at 0x7f25b1587c40>, '_dependencies': namespace(redis=<framework.cache_ext.redis_plugin.RedisPool object at 0x7f25aef694c0>), 'cors': CORSSettings(allow_headers=frozenset({'*'}), allow_methods=frozenset({'options', 'post', 'put', 'head', 'patch', 'get', 'delete'}), allow_origins=(), always_send=True, automatic_options=True, expose_headers=frozenset(), max_age='5', send_wildcard=False, supports_credentials=False)}