只有累積,沒有奇蹟

2023年1月28日 星期六

[回顧] 2022 年個人回顧

前言
2022 年對自己來說是個挑戰非常大的一年,自己回想起來可以是工作 10 幾年來最辛苦的一年 (沒有比較沒有傷害(?。總結 2022 年三個重點,分別是 #管理 #學習 #技術分享,以下就針對 2022 年做個簡單的回顧,記錄自己累到不要不要的內容

課程
▍線下課程
  • CSM AHA
  • LeSS (Large Scale Scrum)入門 - 體驗工作坊

▍線上課程

閱讀書籍
在過去幾年已經有帶團隊的經驗,2022 年遇到最大挑戰是當團隊成員人數是之前的數(4~5)倍時該如何管理
當人數變多,過去管理團隊的方式適用嗎 ?
當人數變多溝通問題開始浮現。如何降低團隊溝通成本呢 ? 如何制定適合團隊的流程與 SOP ?
當人數變多信任感很重要,看到問題如何讓大家知道並願意接受(買單) ? 團隊成員有人不合時該怎麼協調 ?
當人數變多要如何授權,如何有效授權給下面主管避免微管理 ? 團隊的切分怎樣才是最有效率的合作方式呢

或許過去在團隊人數少的時候有些方法沒問題,但團隊到了一定規模時就會遇到瓶頸,因此更應該找到新方法像是上課或是看書加強學習自己未知的知識,透過更多外在刺激與借鏡別人成功的經驗,希望突破自己的天花板找到既有問題的解法,避免自己成為團隊的瓶頸阻礙團隊的發展。自己也很幸運地在過去的工作時有認識厲害的技術管理者,在實務上遇到困難時可以第一時間求助與找到可能的根本問題,經過一年的時間自己也對於管理有進一步的認識,看到自己過去可能不成熟的地方與觀念,在實務上也學到很多好的與不好的經驗與教訓。也看到團隊慢慢朝向好的方向前進。
最近去看了灌籃高手電影版,對於團隊這件事也是很有感觸,回憶起安西教練曾經說過的一段話
「球隊不是為你而存在的,相反的你的存在是為球隊啊」


技術分享
身為技術出生的攻城師當然不能忘本,對於技術當然是要持續學習與精進的,否則久了之後很容易落為嘴砲主管,這並不是我自己想走的路線。也因為有這想法,在年初時也給自己設定目標要持續不要臉的投稿技術演討會分享學習心得,可能是運氣不錯今年投稿的都有得到評審的青睞有機會上台分享,超越了去年 2021 的三場技術分享,但對於容易緊張得自己來說就是可怕的一件事,下半年生活幾乎每個月都在準備研討會討影片講稿,白天工作忙到炸裂,晚上顧家裡陪小孩,半夜準備投影片就是生活剪影不唬爛,但為了達到自己設定的目標還是牙一咬撐過去了,其中讓人意外的是 DevopsDays 議程被排在 ABC 大廳,可能是議題命名的還不錯當時受眾比預期的多很多很多很多,最後參加人數近 300 位主辦單位還加椅子才坐的下,幸好最後聽說議程問卷結果是挺滿意的才讓我的不安散去 XDDD
另外 2022 給自己的另一個目標是要持續的在 FB 粉絲團分享有趣的技術議題,針對不錯的議題要加上小小的見解以提高發文的質量,立志成為高級轉貼仔(誤。成效從年初的 40 位追蹤到現在接近 290 位,也算是有小小的成績也希望自己可以堅持下去

驚喜 : MVP
微軟MVP成就達成 ! 感謝保哥推薦才有機會得到這殊榮,也期望自己莫忘初衷技術學習繼續下去 :)

2023 期望
新年一年,一定會有更多的挑戰
  • 睡飽一點 : 2023 多睡一點 (2022 平均睡眠 4.5 小時 XDD
  • 舉辦分享 : 定期舉辦內部分享,讓同仁可以在忙碌之外吸收新的知識
  • 技術分享 : 繼續不要臉投稿研討會技術分享
  • AMA : 與轄下同仁談任何事情(Ask me anything),不管好的壞的多聽聽大家的想法

希望大家 happy coding , enjoy it :)

2023年1月15日 星期日

[.NET] Quartz.NET 排程執行異常 - All triggers of Job class set to ERROR state.

問題 
最近因為新專案需求是定期到資料庫檢查會員的資料,因此使用 ASP.NET Core Hosting 服務 +  Quartz.NET 作為工作排程器使用,在開發完畢要啟動 Job 驗證正確性時意外跳出異常訊息,錯誤訊息為  Quartz.Simpl.RAMJobStore | All triggers of Job GroupName.ClassName set to ERROR state. ,這篇就針對此案例作簡單紀錄與分享若是有不清楚或是錯誤的地方歡迎討論予糾正

解決方法 
首先先看一下案發現場的錯誤 log 如下
上面可以看到當程式啟動時所紀錄的 Log 資訊,像是有紀錄目前所使用的版本為 3.0.7 版,預設 ThreadPool 為 10 條,但一到 QuartzScheduler 啟動之後下一個 Log 就直接紀錄執行異常 ( ERROR STATE ),搜尋相關異常訊息發現以下資訊
It should be extremely rare for this method to throw an exception - basically only the case where there is no way at all to instantiate and prepare the Job for execution. When the exception is thrown, the Scheduler will move all triggers associated with the Job into the state, which will require human intervention (e.g. an application restart after fixing whatever configuration problem led to the issue with instantiating the Job).
可能問題為 Quartz.NET 啟動此 Trigger 當下發生錯誤,有可能是因為沒有辦法實例化或是準備執行 Job 發生異常,當執行拋出異常時會將有關聯的作業關閉,會自動更新異常 TRIGGER_STATE 狀態為 ERROR state,需要人工進行修復,修復完畢後再重新啟用應用程式。因此下一步是了解啟動時發生的錯誤資訊,為了得到相關錯誤訊息,調整既有的代碼將  JobExecutionException  資訊紀錄在 log.Error 中,
class SomeJob : IJob
{
    private readonly ILogger _logger;
    private readonly IMemberService _service;

    public SomeJob(IMemberService service, ILogger logger)
    {
        this._service = service;
        this._logger = logger;
    }
    
    public Task Execute(IJobExecutionContext context)
    {
        try
        {
            // todo something
        }
        catch (Exception e)
        {
            JobExecutionException je = new JobExecutionException(e);
            je.RefireImmediately = true;  //do something with the exception

            _logger.Error(je);
            
            return Task.FromResult(0);
        }

        return Task.FromResult(0);
    }
}
接著重新執行應用程式,並觀察 Log 資訊
果不其然,透過 Log 可以發現是在 Service 的建構子 ctor 注入時發生錯誤,所以才會在排程要啟動時異常
停止此 Job 的執行動作,在往下追發現是其 interface 存取修飾子設定異常 ( 應該要是 public 實際卻是 internal ),修正後在重新執行可以看到下列 Log,
Quartz.Core.QuartzSchedulerThread|Batch acquisition of 1 triggers |url: |action: 
執行正常,宣告結案 !

參考
Recover from trigger ERROR state after Job constructor threw an exception?

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com