早期為配合特定崗位人員透過郵件回覆「同意」完成審批,開發了一個獨立的郵件審批服務,採用 固定間隔輪詢 郵件伺服器:
缺點明顯:
將「客戶端輪詢」改為「伺服器推送」:
[ServiceContract(CallbackContract = typeof(IMailNotificationCallback))]
public interface IMailSubscriptionService
{
[OperationContract(IsOneWay = true)]
void Subscribe(string clientId);
[OperationContract(IsOneWay = true)]
void Unsubscribe(string clientId);
}
public interface IMailNotificationCallback
{
[OperationContract(IsOneWay = true)]
void OnNewMailReceived(MailMessageDto mail);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MailSubscriptionService : IMailSubscriptionService
{
private static readonly Dictionary<string, IMailNotificationCallback> _subscribers
= new Dictionary<string, IMailNotificationCallback>();
private static readonly object _lock = new object();
public void Subscribe(string clientId)
{
var callback = OperationContext.Current.GetCallbackChannel<IMailNotificationCallback>();
lock (_lock) _subscribers[clientId] = callback;
}
public void Unsubscribe(string clientId)
{
lock (_lock) _subscribers.Remove(clientId);
}
// 郵件伺服器內部呼叫,對外不公開
internal static void NotifyNewMail(MailMessageDto mail)
{
List<IMailNotificationCallback> callbacks;
lock (_lock) callbacks = _subscribers.Values.ToList();
foreach (var cb in callbacks)
{
Task.Run(() =>
{
try { cb.OnNewMailReceived(mail); }
catch { /* 記錄錯誤,移除失效訂閱 */ }
});
}
}
}
public class ApprovalService : IMailNotificationCallback
{
private IMailSubscriptionService _proxy;
private readonly string _clientId = "ApprovalService_01";
public void Start()
{
var context = new InstanceContext(this);
var factory = new DuplexChannelFactory<IMailSubscriptionService>(
context, "MailSubscriptionEndpoint");
_proxy = factory.CreateChannel();
_proxy.Subscribe(_clientId);
}
public void OnNewMailReceived(MailMessageDto mail)
{
// 異步處理解析與審批,避免阻塞 Callback 執行緒
Task.Run(() => ProcessMailAsync(mail));
}
private async Task ProcessMailAsync(MailMessageDto mail)
{
// 解析郵件、提取單據、呼叫審批引擎...
}
}
WCF 雙工通訊完美契合「事件驅動」場景,將輪詢改為訂閱發佈,不僅解決即時性與資源浪費,更為未來分散式擴展奠定基礎。雖郵件解析複雜度仍存,但架構層面已邁出關鍵一步。