昔者,有客臨門,亟需自石墨文庫中擷取卷帙若干。此等文冊,非止一卷,乃累牘連篇,亟需批量轉置。然吾輩慮及用戶體驗,當效東坡"腹有詩書氣自華"之雅意,使操作如行云流水,遂定以條分縷析之法,列其要目于屏間,令觀者一目了然,恰似"大江東去,浪淘盡"之暢達,去繁就簡,存精去蕪,使界面如清風明月,操作若庖丁解牛。具體之法,容后詳敘…
上傳流程介紹
石墨云臺藏機杼,以鏈為引可通幽。昔者匠人剖玉,今人截鏈取牘,得十六位秘鑰,若敦煌經卷之編號,暗藏玄機。其法非獨單卷,亦通全冊,或拓一室之藏,但添協作者于卷軸、函匣、書閣之間,如邀蘇子瞻共游赤壁,許其同覽文海。然需筑私邸于云中(私有化部署),方得啟下載之門徑,此間玄妙,非市井可窺。
進度條之藝,恰似東坡觀潮:初見細浪如銀線,漸涌為雪堆千疊,終成驚濤拍岸之勢。其理有三:一曰分黍定寸(任務切分),二曰燃香計時(進度追蹤),三曰墨染絹帛(界面渲染)。每完成一卷,則添一筆于素箋,恰似東坡夜游承天寺,見"庭下如積水空明",步步生輝。其間奧義,非止術數,更含天地運行之理,今且述其梗概,余者待諸君細參。
服務流程示意圖
文樞流轉之法,恰似東坡治水之道。用戶執鏈如持竹簡,錄于云臺(系統界面),此乃"大江初發昆侖源"之始。后端服務承此簡牘,以密鑰為符,協作者為印,啟石墨秘庫之門,如子瞻開赤壁石壁,得見卷帙浩繁。
所得文牘既至,當效東坡"腹中貯書一萬卷"之法,分存于Redis玉匣。業務層為匠人,執進度之筆,于玉匣刻痕記數,初若"輕舟已過萬重山"之速,漸成"千帆競發爭上游"之勢,終顯"百川東到海"之成。其間刻痕深淺,皆映下載之進度,恰似東坡觀潮,見"素練橫江,雪浪排空"之景。
Talk is easy show me the code
redis存儲類實體類
public class RedisTaskProcess {@Schema(description = "消息id")private String taskId;@Schema(description = "業務類型,定義自己的任務類型xxxxx")private String businessType;@Schema(description = "處理進度的百分比")private BigDecimal processPercent;@Schema(description = "任務狀態, processing|completed|error|cancel")private String status = "processing";@Schema(description = "消息描述, 異常時或者特殊場景會指定消息")private String msg;@Schema(description = "用戶編碼,用于獲取任務Key")private String userCode;@Schema(description = "任務標題(文件名)")private String title;@Schema(description = "創建時間")private Long createTime;/*** 啟動一個長任務處理流程,并返回任務處理響應對象。* * @param businessType 業務類型,用于標識任務的業務場景。* @param userCode 用戶代碼,標識發起任務的用戶。* @param title 任務標題,用于描述任務內容。* @param redisTemplate Redis模板對象,用于將任務信息存儲到Redis中。* @return LongTaskProcessResponse 返回長任務處理響應對象,包含任務ID、狀態、進度等信息。*/
public static RedisTaskProcess commonStart(String businessType, String userCode, String title, RedisTemplate<String, Object> redisTemplate) {// 初始化長任務處理響應對象RedisTaskProcess res = new RedisTaskProcess();// 設置任務ID、業務類型、狀態、消息、標題、進度、用戶代碼和創建時間res.setTaskId(IdUtil.getSnowflakeNextIdStr());res.setBusinessType(businessType);res.setStatus("processing");res.setMsg("開始處理");res.setTitle(title);res.setProcessPercent(new BigDecimal(1));res.setUserCode(userCode);res.setCreateTime(System.currentTimeMillis());// 將任務信息存儲到Redis中,并設置過期時間為1天redisTemplate.opsForValue().set(res.findTaskCacheKey(), res, 1, TimeUnit.DAYS);return res;
}/*** 完成任務的通用方法,用于設置任務狀態為“已完成”,并更新相關信息到Redis緩存中。** @param completeMsg 任務完成時的消息內容,用于設置任務的msg字段。* @param redisTemplate Redis操作模板,用于將任務信息存儲到Redis緩存中。*/
public void commonComplete(String completeMsg, RedisTemplate<String, Object> redisTemplate) {// 設置任務狀態為“已完成”this.setStatus("completed");// 設置任務完成消息this.setMsg(completeMsg);// 設置任務進度為100%this.setProcessPercent(new BigDecimal(100));// 設置任務創建時間為當前時間this.setCreateTime(System.currentTimeMillis());// 將任務信息存儲到Redis緩存中,并設置過期時間為1天redisTemplate.opsForValue().set(this.findTaskCacheKey(), this, 1, TimeUnit.DAYS);
}/*** 執行通用的更新操作,并調用重載的 `commonUpdate` 方法。** @param status 當前狀態信息,通常用于表示操作的狀態。* @param msg 更新操作的消息或描述信息。* @param addPercent 需要增加的百分比值,通常用于表示進度或比例的增加。* @param redisTemplate Redis 操作模板,用于與 Redis 進行交互。*/
public void commonUpdate(String status, String msg, Integer addPercent, RedisTemplate<String, Object> redisTemplate) {this.commonUpdate(status, msg, addPercent, null, redisTemplate);
}/*** 更新任務狀態信息,并將更新后的任務信息存儲到Redis中。** @param status 任務狀態,用于設置當前任務的狀態。* @param msg 任務消息,用于設置當前任務的消息內容。* @param addPercent 增加的進度百分比,用于計算當前任務的進度。* @param title 任務標題,如果非空則更新任務的標題。* @param redisTemplate Redis模板對象,用于將任務信息存儲到Redis中。*/
public void commonUpdate(String status, String msg, Integer addPercent, String title, RedisTemplate<String, Object> redisTemplate) {// 設置任務狀態和消息this.setStatus(status);this.setMsg(msg);// 如果提供了任務標題,則更新標題if (title != null) {this.setTitle(title);}// 計算并更新任務進度,確保進度不超過99%BigDecimal calRes = this.getProcessPercent().add(new BigDecimal(addPercent));this.setProcessPercent(calRes.min(new BigDecimal(99)));// 設置任務的創建時間this.setCreateTime(System.currentTimeMillis());// 將更新后的任務信息存儲到Redis中,并設置過期時間為1天redisTemplate.opsForValue().set(this.findTaskCacheKey(), this, 1, TimeUnit.DAYS);
}/*** 處理通用失敗情況,并將失敗信息存儲到Redis中。** 該方法將當前對象的狀態設置為"error",并設置失敗信息。同時,記錄當前時間作為創建時間,* 并將整個對象存儲到Redis中,緩存時間為1天。** @param failMsg 失敗信息,用于描述失敗的原因或詳情。* @param redisTemplate Redis操作模板,用于與Redis進行交互。*/
public void commonFailure(String failMsg, RedisTemplate<String, Object> redisTemplate) {// 設置狀態為"error",表示任務失敗this.setStatus("error");// 設置失敗信息this.setMsg(failMsg);// 記錄當前時間作為創建時間this.setCreateTime(System.currentTimeMillis());// 將當前對象存儲到Redis中,緩存時間為1天redisTemplate.opsForValue().set(this.findTaskCacheKey(), this, 1, TimeUnit.DAYS);
}/*** 生成任務緩存的唯一鍵。** 該函數通過將任務處理前綴、用戶代碼和任務ID拼接成一個字符串,生成一個唯一的緩存鍵。* 該鍵通常用于在緩存系統中標識和存儲與特定任務相關的數據。** @return 返回一個格式化的字符串,表示任務緩存的唯一鍵。格式為:"任務處理前綴:用戶代碼:任務ID"。*/
public String findTaskCacheKey() {return String.format("%s:%s:%s", TASK_PROCESS_PREFIX_KEY, this.userCode, this.taskId);
}}
上傳服務偽代碼
public void updatexxxx{try{// 業務測文件集合List fileIdList = new ArrayList();// 業務代碼填充xxxxxxx// 初始化進度響應對象RedisTaskProcess redisTaskProcess = RedisTaskProcess.commonStart("業務代碼","業務代碼","業務代碼");// 計算文件進度int documentationProgress = 99 / fileIdList.size();// 指定上傳邏輯偽代碼fileIdList.forEach(fileId -> {// 業務代碼邏輯xxxxxx// 更新文件進度redisTaskProcess..commonUpdate("processing", "正在處理文件: " + save.getFileName(), progressIncrement, redisTemplate);})// 完成長傳邏輯commonComplete("文檔下載完成", redisTemplate);} catch {log.error("文檔下載處理失敗", e);redisTaskProcess.commonFailure("文檔下載處理失敗: " + e.getMessage(), redisTemplate);throw new RuntimeException(e);}}
昔者東坡治水,知"急流須用緩沙堤"之理。今以Redis玉匣存進度,雖得"輕舟已過萬重山"之速,然遇千帆競渡之時,猶恐"驚濤拍岸卷千堆雪"。蓋因弦歌未絕,已有新篙入水,玉匣刻痕易為后浪所湮,此乃"前度劉郎今又來"之困也。
欲解此困,當效東坡"廬山煙雨浙江潮"之禪機:或借WATCH法眼觀潮,察毫厘之變;或運Lua神筆,繪原子之章。其間妙理,非止于術,更在"不識廬山真面目"之破局——使進度刻痕如西子湖心月,任爾千帆過盡,自有清輝長明。然此中三昧,且待下回分說,恰似"欲把西湖比西子"之未盡余韻…