RMS Mail-ის ყველა მნიშვნელოვანი ცვლილება ჩაიწერება ამ ფაილში.
\Seen Flag იმპლემენტაცია — ორმხრივი წაკითხვის მდგომარეობის სინქრონიზაციაIMAP-ის \Seen flag მთლიანად იგნორირებული იყო ორივე მიმართულებით. ელფოსტები ყოველთვის ჩასმული იყო როგორც is_read=false(გარდა Sent საქაღალდეებისა), და ლოკალური წაკითხული/წაუკითხავი ცვლილებები არასოდეს იყო გაგზავნილი IMAP სერვერზე.
IMAP → RMS (კითხვა \Seen):
fetcher.go: ProcessMessage და ProcessMessageToFolder ახლა აანალიზებენ msg.Flags და აყენებენ email.IsRead = true როდესაც \Seen არის წარმოდგენილი. ადრე ყოველთვის false.ატომური ON CONFLICT (შეჯიბრის მდგომარეობის დაცვა):
SaveEmailToFolder და SaveEmail ორივე PostgreSQL-სა და SQLite-ში: ON CONFLICT ... DO UPDATE SET is_read = CASE WHEN emails.is_dirty_locally THEN emails.is_read ELSE EXCLUDED.is_read END. თუ მომხმარებელმა შეცვალა წაკითხვის მდგომარეობა ლოკალურად (is_dirty_locally=true), სერვერის მნიშვნელობა არ იწერება თავზე. წინააღმდეგ შემთხვევაში, სინქრონიზაცია განახლდება IMAP-დან \Seen.RMS → IMAP (გაგზავნა \Seen):
worker.go: syncFlags() — მთავარი სინქრონიზაციის ციკლის შემდეგ, ითხოვს GetDirtyEmails (LIMIT 500), ჯგუფდება წაკითხული/წაუკითხავი სტატუსის მიხედვით, აგზავნის პაკეტირებულ IMAP STORE command-ებს (200 UID თითოეულ პაკეტში StoreFlagsAdd/StoreFlagsDel).ClearDirtyFlag(): აახლებს is_dirty_locally=false წარმატებული IMAP flag სინქრონიზაციის შემდეგ.webhook_retry_queue table + background Go ticker) webhooks-ისთვის Mono edition-ში. ეს უზრუნველყოფს, რომ webhook retries გადარჩეს კონტეინერის გადატვირთვას, რაც Mono-ს საიმედოობას Unified edition-ის Redis ZSET queue-ს დონეზე აყენებს.GetDirtyEmails(ctx, accountID) ([]Email, error): აბრუნებს ელფოსტებს is_dirty_locally=true, გამოკლებით drafts (ცალკე GetDirtyDrafts path)ClearDirtyFlag(ctx, emailID) error: ასუფთავებს dirty flag-ს წარმატებული IMAP STORE-ის შემდეგSyncStore interface: ორივე მეთოდი დაემატა sync package interface-ს, არსებულ GetDirtyDraftsisLicensed): მთლიანად გადაწერილია, რათა იყოს non-blocking. ის ახლა უპირობოდ აბრუნებს cached-მნიშვნელობას მყისიერად და იღებს live DB სტატუსს ასინქრონულად ფონზე. Fail-open თავდაპირველ ჩატვირთვაზე უზრუნველყოფს ნულოვან ბლოკირებას პირველ მოთხოვნაზე.goroutine) და უპირობოდ აბრუნებს {"status": "ok"} frontend-სთვის მყისიერად. ეს ხელს უშლის UI-ს გაყინვას, თუ RMS ლიცენზიის სერვერი მიუწვდომელია.პარალელური ფონური ინდექსის აგება (CREATE INDEX CONCURRENTLY 64 პარტიციაზე) გაჯერებს დისკის I/O-ს და ამოწურა PostgreSQL კავშირების პული. ამან გამოიწვია უკავშირო API მოთხოვნების—კერძოდ isLicensed და GetUnreadCount—timeout-მდე.
isLicensed timeouts-ები არასწორად გაშვებული is_locked: true frontend-ზე, მყისიერად აგდებდა მომხმარებლებს. დანერგილია sync.RWMutex backed 30-წამიანი TTL ქეში, და 5-წუთიანი გრეისული fallback-ით, თუ მონაცემთა ბაზის მოთხოვნა ჩავარდება.time.Sleep(2 * time.Second) pause (FTS) partition ინდექსების შექმნებს შორის in RunBackgroundOptimizations რათა მონაცემთა ბაზამ ისუნთქოს (breathe) და მომხმარებელთა მოთხოვნები მოემსახუროს.buildFTSPartitions call in main.go with store.RunBackgroundOptimizations(context.Background()).invalid operation: store ... is not an interface. SQLite driver-ი აბრუნებს კონკრეტული pointer ტიპს *sqlite.Storage ინტერფეისის ნაცვლად, რაც იწვევს RunBackgroundOptimizations type assertion-ის (ტიპის მტკიცების) კომპილაციის ჩავარდნის მიზეზი. იქნა მოხვეული (wrapped) any(store) Go compiler-ის (Go კომპილატორის) დაკმაყოფილების მიზნით ორივე edition-ისთვის.ჯგუფის სახელები (Group names) without truncate color dot-ი (ფერის წერტილი) გადაჰყავდა outside overflow-hidden container-იდან. დაფიქსირებული: shrink-0 arrow/dot/count-ზე, min-w-0 truncate name-ზე, is_locked badge (სამკერდე) გადატანილია name span-ის (სახელის span) გარეთ.
Correlated subquery (კორელირებული ქვემოთხოვნა) replaced (შეიცვალა) WITH inbox_unread AS (...) CTE. 3 group subqueries × 250K emails → single hash join ~500 filtered row-ზე.
\Seen ON CONFLICT-ის ადრე overwrite-ებდა Server State-სორიგინალი ON CONFLICT DO UPDATE SET is_read = emails.is_read ყოველთვის ინახავდა DB value-ს, თუნდაც first sync-ზე, where \Seen should იყოს source of truth (ჭეშმარიტების წყარო). New CASE WHEN logic (ლოგიკა) correctly (სწორად) განასხვავებს first sync-ს (პირველი სინქრონიზაცია) local modifications-ისგან (ლოკალური მოდიფიკაციები).