mirror of
https://github.com/JefferyHcool/BiliNote.git
synced 2026-08-29 12:07:21 +08:00
BcutTranscriber 被 transcriber_provider 缓存复用,但 __etags 等上传 会话状态只在 __init__ 清空、每次上传只追加,导致容器启动后第二次 及以后的转写提交的 etag 数与分片数不符,B 站返回"第三方服务异常"。 并发提交多个视频时,多个后台任务还会在同一实例上交错上传,etag 互相混入。 - _upload() 开头重置全部上传会话状态,修串行残留 - transcript() 加实例锁,整个转写会话串行执行,修并发交错 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
2.4 KiB
Python
75 lines
2.4 KiB
Python
import json
|
|
|
|
from app.transcriber import bcut as bcut_module
|
|
from app.transcriber.bcut import BcutTranscriber
|
|
|
|
|
|
class _FakeResp:
|
|
def __init__(self, payload=None, etag=""):
|
|
self._payload = payload or {}
|
|
self.headers = {"Etag": etag}
|
|
self.url = ""
|
|
|
|
def raise_for_status(self):
|
|
pass
|
|
|
|
def json(self):
|
|
return self._payload
|
|
|
|
|
|
class _FakeSession:
|
|
"""模拟必剪上传三步接口:申请上传 / PUT 分片 / 提交合并"""
|
|
|
|
def __init__(self, per_size, upload_urls_count):
|
|
self.per_size = per_size
|
|
self.upload_urls_count = upload_urls_count
|
|
self.commit_payloads = []
|
|
|
|
def post(self, url, data=None, headers=None):
|
|
if url == bcut_module.API_REQ_UPLOAD:
|
|
body = json.loads(data)
|
|
return _FakeResp({
|
|
"data": {
|
|
"in_boss_key": "boss",
|
|
"resource_id": "res",
|
|
"upload_id": "up",
|
|
"upload_urls": [f"http://fake/{i}" for i in range(self.upload_urls_count)],
|
|
"per_size": self.per_size,
|
|
"size": body["size"],
|
|
}
|
|
})
|
|
if url == bcut_module.API_COMMIT_UPLOAD:
|
|
self.commit_payloads.append(json.loads(data))
|
|
return _FakeResp({"code": 0, "data": {"download_url": "http://fake/dl"}})
|
|
raise AssertionError(f"unexpected post: {url}")
|
|
|
|
def put(self, url, data=None, headers=None):
|
|
return _FakeResp(etag=f"etag-{url[-1]}")
|
|
|
|
|
|
def _upload_file(transcriber, tmp_path, name, content, chunks):
|
|
f = tmp_path / name
|
|
f.write_bytes(content)
|
|
transcriber.session = _FakeSession(per_size=5, upload_urls_count=chunks)
|
|
transcriber._upload(str(f))
|
|
return transcriber.session.commit_payloads
|
|
|
|
|
|
def test_second_upload_commits_only_its_own_etags(tmp_path):
|
|
t = BcutTranscriber()
|
|
|
|
# 第一次:3 字节,1 分片
|
|
commits = _upload_file(t, tmp_path, "a.mp3", b"aaa", chunks=1)
|
|
assert len(commits[0]["Etags"].split(",")) == 1
|
|
|
|
# 第二次(同一实例):8 字节,2 分片——修复前会提交 3 个 etag
|
|
commits = _upload_file(t, tmp_path, "b.mp3", b"aaaaaaaa", chunks=2)
|
|
assert len(commits[0]["Etags"].split(",")) == 2
|
|
|
|
|
|
def test_first_upload_unchanged(tmp_path):
|
|
t = BcutTranscriber()
|
|
commits = _upload_file(t, tmp_path, "a.mp3", b"aaa", chunks=1)
|
|
assert commits[0]["Etags"] == "etag-0"
|
|
assert commits[0]["UploadId"] == "up"
|