/// <summary> /// Enable the synchronization of individual folders or Room[s] /// </summary> /// <param name="folderInfo"></param> public void ProcessChanges(EWSFolderInfo folderInfo) { bool moreChangesAvailable = false; _traceListener.Trace("SyncProgram", $"Entered ProcessChanges for {folderInfo.SmtpAddress} at {DateTime.UtcNow}"); using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database)) { var room = context.RoomListRoomEntities.FirstOrDefault(f => f.SmtpAddress.Equals(folderInfo.SmtpAddress)); var email = room.SmtpAddress; var syncState = room.SynchronizationState; var syncTimestamp = room.SynchronizationTimestamp; try { do { // Get all changes since the last call. The synchronization cookie is stored in the _SynchronizationState field. _traceListener.Trace("SyncProgram", $"Sync changes {email} with timestamp {syncTimestamp}"); // Just get the IDs of the items. // For performance reasons, do not use the PropertySet.FirstClassProperties. var changes = folderInfo.Service.Current.SyncFolderItems(folderInfo.Folder, PropertySet.IdOnly, null, 512, SyncFolderItemsScope.NormalItems, syncState); // Update the synchronization syncState = changes.SyncState; // Process all changes. If required, add a GetItem call here to request additional properties. foreach (ItemChange itemChange in changes) { // This example just prints the ChangeType and ItemId to the console. // A LOB application would apply business rules to each _traceListener.Trace("SyncProgram", $"ChangeType = {itemChange.ChangeType} with ItemId {itemChange.ItemId.ToString()}"); // Send an item event you can bind to var service = System.Threading.Tasks.Task.Run(async() => { _traceListener.Trace("SyncProgram", "In Thread run await...."); await Messenger.SendQueueO365SyncFoldersAsync(queueSync, email, itemChange); }, CancellationTokenSource.Token); service.Wait(); } // If more changes are available, issue additional SyncFolderItems requests. moreChangesAvailable = changes.MoreChangesAvailable; room.SynchronizationState = syncState; room.SynchronizationTimestamp = DateTime.UtcNow; var roomchanges = context.SaveChanges(); _traceListener.Trace("SyncProgram", $"Room event folder sync {roomchanges} persisted."); }while (moreChangesAvailable); } catch (Exception processEx) { Trace.TraceError($"Failed to send queue {processEx.Message}"); } finally { room.SynchronizationState = syncState; room.SynchronizationTimestamp = DateTime.UtcNow; var roomchanges = context.SaveChanges(); _traceListener.Trace("SyncProgram", $"Failed ProcessChanges({email}) folder sync {roomchanges} persisted."); } } }
/// <summary> /// Establish the connection /// </summary> /// <returns></returns> async private System.Threading.Tasks.Task RunAsync() { _traceListener = new ClassTraceListener(); IsDisposed = false; EwsToken = await EWSConstants.AcquireTokenAsync(); Messenger = new MessageManager(CancellationTokenSource); ServiceCredentials = new OAuthCredentials(EwsToken.AccessToken); _reconnect = true; _groups = new Dictionary <string, GroupInfo>(); _mailboxes = new Mailboxes(ServiceCredentials, _traceListener); _subscriptions = new List <SubscriptionCollection>(); _connections = new Dictionary <string, StreamingSubscriptionConnection>(); var impersonationId = EWSConstants.Config.Exchange.ImpersonationAcct; try { var list = new List <EWSFolderInfo>(); using (EWSDbContext context = new EWSDbContext(EWSConstants.Config.Database)) { foreach (var room in context.RoomListRoomEntities.Where(w => !string.IsNullOrEmpty(w.Identity))) { var mailboxId = room.SmtpAddress; try { var roomService = new EWService(EwsToken); roomService.SetImpersonation(ConnectingIdType.SmtpAddress, mailboxId); var folderId = new FolderId(WellKnownFolderName.Calendar, mailboxId); var info = new EWSFolderInfo() { SmtpAddress = mailboxId, Service = roomService, Folder = folderId }; list.Add(info); } catch (Exception srex) { _traceListener.Trace("SyncProgram", $"Failed to ProcessChanges{srex.Message}"); throw new Exception($"ProcessChanges for {mailboxId} with MSG:{srex.Message}"); } } } // Parallel ForEach (on RoomMailbox Grouping and SyncFolders) await System.Threading.Tasks.Task.Run(() => { ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = maxConcurrency }; // Fireoff folder sync in background thread Parallel.ForEach(list, options, (bodyInfo) => { ProcessChanges(bodyInfo); }); }); var tasks = new List <System.Threading.Tasks.Task>(); if (EWSConstants.Config.Exchange.PullEnabled) { // Upon completion tick repeater to poll subscriptions tasks.Add(PullSubscriptionChangesAsync(impersonationId)); } else { // Upon completion kick of streamingsubscription tasks.Add(CreateStreamingSubscriptionGroupingAsync(impersonationId)); } System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); } catch (Exception ex) { Trace.TraceError(ex.Message); } }