MailCore / mailcore2

MailCore 2 provide a simple and asynchronous API to work with e-mail protocols IMAP, POP and SMTP. The API has been redesigned from ground up.
Other
2.6k stars 625 forks source link

How to cancel long running operations like MCOIMAPFetchContentOperation or MCOIMAPFolderStatusOperation #226

Closed palaniraja closed 11 years ago

palaniraja commented 11 years ago

There is a start method to start an async operation . At times I would like to cancel the operations initiated earlier. For example, I list the available folders and last known state from local database and start the folder status operation. Before the operation return any results, people would choose the folder and move to messagesviewcontroller.

I would like to know if there are any way I could stop the operation.

palaniraja commented 11 years ago

Sorry, I found the cancel method defined in MCOOperation. Kindly ignore, also feel free to correct me if I'm wrong.

palaniraja commented 11 years ago

But it doesn't seem to work, Can someone confirm?

dinhvh commented 11 years ago

In the implementation of cancel for IMAP operation, we choose to leave the operation finish and return no result. Does it match the behavior?

palaniraja commented 11 years ago

I am expecting such a behaviour but I still receive logs of operation which return the value.

on viewDidLoad I have this code

//This is to get folder status
self.fstatusop =  [[[CTMAccount sharedSession] imapsession] folderStatusOperation:folder.folderTitle];
        [self.fstatusop start:^(NSError *error, MCOIMAPFolderStatus *status) {
            [self updateUnreadCount:status.unseenCount ForFolder:folder.folderTitle];
            folder.folderUnreadCount = status.unseenCount;
            //Some log statements & db update query to save the unread count to database.
            [self.keyFolders setObject:folder forKey:key];
            [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
        }];

if the user selects a folder before this operation return, i call the following in tableview:didselectrowatindexpath:

[self.fstatusop cancel];
//push to viewcontroller that list all the emails of the folder

but even after traversing to next viewcontroller, I'm still getting the connectlogger debug inputs as below:

2013-07-22 20:37:27.569 APPNAME[45236:c07] <FMDatabase: 0xad879c0> executeUpdate: UPDATE tbl_folders SET f_unread_count = ? WHERE f_title = ? 
2013-07-22 20:37:27.569 APPNAME[45236:c07] obj: 12
2013-07-22 20:37:27.570 APPNAME[45236:c07] obj: [Gmail]/All Mail
2013-07-22 20:37:27.572 APPNAME[45236:4d03] CLogger: 1 withData: 8 STATUS "[Gmail]/Spam" (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY)
2013-07-22 20:37:27.921 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "[Gmail]/Spam" (MESSAGES 0 RECENT 0 UIDNEXT 3 UIDVALIDITY 3 UNSEEN 0)
8 OK Success
2013-07-22 APPNAME:27.921 APPNAME[45236:4d03] CLogger: 1 withData: 9 STATUS WORK (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY)
2013-07-22 20:37:28.273 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "WORK" (MESSAGES 10 RECENT 0 UIDNEXT 11 UIDVALIDITY 12 UNSEEN 6)
9 OK Success
2013-07-22 APPNAME:28.273 APPNAME[45236:c07] folder unseen count: 6
2013-07-22 20:37:28.274 APPNAME[45236:c07] <FMDatabase: 0xad879c0> executeUpdate: UPDATE tbl_folders SET f_unread_count = ? WHERE f_title = ? 
2013-07-22 20:37:28.274 APPNAME[45236:c07] obj: 6
2013-07-22 20:37:28.275 APPNAME[45236:c07] obj: WORK
2013-07-22 20:37:28.278 APPNAME[45236:4d03] CLogger: 1 withData: 10 STATUS Projects (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY)
2013-07-22 20:37:28.627 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "Projects" (MESSAGES 5 RECENT 0 UIDNEXT 6 UIDVALIDITY 14 UNSEEN 3)
10 OK SuccessAPPNAME
dinhvh commented 11 years ago

It's expected that the connectionLogger will still output debug info.

Hoa V. Dinh

On Monday, July 22, 2013 at 8:12 AM, palaniraja wrote:

I am expecting such a behaviour but I still receive logs of operation which return the value. on viewDidLoad I have this code //This is to get folder status self.fstatusop = [[[CTMAccount sharedSession] imapsession] folderStatusOperation:folder.folderTitle]; [self.fstatusop start:^(NSError error, MCOIMAPFolderStatus status) { [self updateUnreadCount:status.unseenCount ForFolder:folder.folderTitle]; folder.folderUnreadCount = status.unseenCount; [self.keyFolders setObject:folder forKey:key]; [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone]; }];
if the user selects a folder before this operation return, i call the following in tableview:didselectrowatindexpath: [self.fstatusop cancel]; //push to viewcontroller that list all the emails of the folder
but even after traversing to next viewcontroller, I'm still getting the connectlogger debug inputs as below: 2013-07-22 20:37:27.569 APPNAME[45236:c07] <FMDatabase: 0xad879c0> executeUpdate: UPDATE tbl_folders SET f_unread_count = ? WHERE f_title = ? 2013-07-22 20:37:27.569 APPNAME[45236:c07] obj: 12 2013-07-22 20:37:27.570 APPNAME[45236:c07] obj: [Gmail]/All Mail 2013-07-22 20:37:27.572 APPNAME[45236:4d03] CLogger: 1 withData: 8 STATUS "[Gmail]/Spam" (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY) 2013-07-22 20:37:27.921 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "[Gmail]/Spam" (MESSAGES 0 RECENT 0 UIDNEXT 3 UIDVALIDITY 3 UNSEEN 0) 8 OK Success 2013-07-22 APPNAME:27.921 APPNAME[45236:4d03] CLogger: 1 withData: 9 STATUS WORK (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY) 2013-07-22 20:37:28.273 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "WORK" (MESSAGES 10 RECENT 0 UIDNEXT 11 UIDVALIDITY 12 UNSEEN 6) 9 OK Success 2013-07-22 APPNAME:28.273 APPNAME[45236:c07] folder unseen count: 6 2013-07-22 20:37:28.274 APPNAME[45236:c07] <FMDatabase: 0xad879c0> executeUpdate: UPDATE tbl_folders SET f_unread_count = ? WHERE f_title = ? 2013-07-22 20:37:28.274 APPNAME[45236:c07] obj: 6 2013-07-22 20:37:28.275 APPNAME[45236:c07] obj: WORK 2013-07-22 20:37:28.278 APPNAME[45236:4d03] CLogger: 1 withData: 10 STATUS Projects (UNSEEN MESSAGES RECENT UIDNEXT UIDVALIDITY) 2013-07-22 20:37:28.627 APPNAME[45236:4d03] CLogger: 0 withData: * STATUS "Projects" (MESSAGES 5 RECENT 0 UIDNEXT 6 UIDVALIDITY 14 UNSEEN 3) 10 OK SuccessAPPNAME

— Reply to this email directly or view it on GitHub (https://github.com/MailCore/mailcore2/issues/226#issuecomment-21350765).

palaniraja commented 11 years ago

yes, but the code inside the start block executed, which you can see in the console.

2013-07-22 APPNAME:28.273 APPNAME[45236:c07] folder unseen count: 6
2013-07-22 20:37:28.274 APPNAME[45236:c07] <FMDatabase: 0xad879c0> executeUpdate: UPDATE tbl_folders SET f_unread_count = ? WHERE f_title = ? 
2013-07-22 20:37:28.274 APPNAME[45236:c07] obj: 6
2013-07-22 20:37:28.275 APPNAME[45236:c07] obj: WORK

I removed the nslog statement from the code snippet i pasted last time. From the above console log you can see the folder unseen count is printed along with fmdatabase logs (there is one more line i removed, which update the unread count to local sqlite)

Thank you.

dinhvh commented 11 years ago

If you do the following, is the block still called?

//This is to get folder status
self.fstatusop =  [[[CTMAccount sharedSession] imapsession] folderStatusOperation:folder.folderTitle];
[self.fstatusop start:^(NSError *error, MCOIMAPFolderStatus *status) {
  [self updateUnreadCount:status.unseenCount ForFolder:folder.folderTitle];
  folder.folderUnreadCount = status.unseenCount;
  //Some log statements & db update query to save the unread count to database.
  [self.keyFolders setObject:folder forKey:key];
  [self.tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:i inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
}];
[self.fstatusop cancel];

Do you have code sample that would reproduce the issue?

palaniraja commented 11 years ago

calling it in next line does behave as expected just connection logger outputs as mentioned. I will try to extract the code from my project and provide sample.

I am just realizing that I am running this inside a loop, could be the reason as I just cancel one instance when user navigate to next view-controller.

I'm closing it for now, will reopen once I reproduce this with sample code.