MojErr MovePopEmailsCommand::EmailsMovedResponse(MojObject& response, MojErr err) { try { ErrorToException(err); ActivityBuilder ab; m_client.GetActivityBuilderFactory()->BuildMoveEmailsWatch(ab); m_activity->UpdateAndComplete(m_client, ab.GetActivityObject()); m_msg->replySuccess(); if (m_inboxEmailsMoved.size() > 0) { // add the list of UIDs into UidCache GetUidCache(); } else { Complete(); } } catch (const std::exception& ex) { m_msg->replyError(MojErrInternal, ex.what()); Failure(ex); } catch (...) { m_msg->replyError(MojErrInternal); Failure(MailException("unknown exception", __FILE__, __LINE__)); } return MojErrNone; }
void ScheduleRetryCommand::ScheduleRetry() { ActivityBuilder ab; // Get current retry interval from account EmailAccount::RetryStatus retryStatus = m_client.GetAccount()->GetRetry(); int interval = retryStatus.GetInterval(); if(interval <= INITIAL_RETRY_SECONDS) { interval = INITIAL_RETRY_SECONDS; } else if(interval >= MAX_RETRY_SECONDS) { interval = MAX_RETRY_SECONDS; } else { // TODO: only update this on actual retry? interval *= RETRY_MULTIPLIER; } // Update account just in case it wasn't within the limit retryStatus.SetInterval(interval); m_client.GetAccount()->SetRetry(retryStatus); m_client.GetActivityBuilderFactory()->BuildFolderRetrySync(ab, m_folderId, interval); MojErr err; MojObject payload; err = payload.put("activity", ab.GetActivityObject()); ErrorToException(err); err = payload.put("start", true); ErrorToException(err); err = payload.put("replace", true); MojLogInfo(m_log, "Creating retry activity in activity manager: %s", AsJsonString(payload).c_str()); m_client.SendRequest(m_scheduleRetrySlot, "com.palm.activitymanager", "create", payload); }
void PopAccountUpdateCommand::UpdateAccountWatchActivity() { CommandTraceFunction(); try { MojObject revPop; MojErr err = m_transportObj.getRequired("_revPop", revPop); ErrorToException(err); ActivityBuilder ab; m_activityBuilderFactory->BuildAccountPrefsWatch(ab, revPop); MojObject payload; err = payload.put("activity", ab.GetActivityObject()); ErrorToException(err); err = payload.put("start", true); ErrorToException(err); err = payload.put("replace", true); ErrorToException(err); m_client.SendRequest(m_createActivitySlot, "com.palm.activitymanager", "create", payload); } catch (const std::exception& ex) { Failure(ex); } catch (...) { Failure(MailException("unknown exception", __FILE__, __LINE__)); } }
void SyncSession::UpdateScheduledSyncActivity() { MojLogInfo(m_log, "updating scheduled sync activity on folder %s", AsJsonString(m_folderId).c_str()); PopClient::AccountPtr account = m_client.GetAccount(); MojObject accountId = account->GetAccountId(); ActivityBuilder ab; if(!account->IsManualSync()) { int interval = account->GetSyncFrequencyMins(); MojLogInfo(m_log, "setting sync interval to %d minutes", interval); m_builderFactory->BuildScheduledSync(ab, interval); MojObject actObj = ab.GetActivityObject();; MojLogInfo(m_log, "Replacing scheduled activity: %s", AsJsonString(actObj).c_str()); m_activities->ReplaceActivity(ab.GetName(), actObj); } else { MojString scheduledActName; m_builderFactory->GetScheduledSyncActivityName(scheduledActName); // Remove activity ActivityPtr activity = m_activities->GetOrCreateActivity(scheduledActName); activity->SetEndAction(Activity::EndAction_Cancel); } }
void ImapActivityFactory::SetNetworkRequirements(ActivityBuilder& ab, bool requireFair) { ab.SetRequiresInternet(false); if(requireFair && !ImapConfig::GetConfig().GetIgnoreNetworkStatus()) { ab.SetRequiresInternetConfidence("fair"); } }
void ActivityBuilderFactory::BuildScheduledSync(ActivityBuilder &builder, int intervalMins) { // activity to setup watch MojString name; GetScheduledSyncActivityName(name); // description of watch MojString desc; GetScheduledSyncActivityDesc(desc); // sync interval in seconds int intervalSecs = MinsToSecs(intervalMins); builder.SetName(name.data()); builder.SetDescription(desc.data()); builder.SetPersist(true); builder.SetExplicit(true); builder.SetRequiresInternet(false); builder.SetSyncInterval(0, intervalSecs); builder.SetImmediate(true, "low"); // setup parameters (to be sent when trigger is called) MojObject params; MojErr err = params.put(PopAccountAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); builder.SetCallback(SCHEDULED_SYNC_CALLBACK, params); // put accountId in metadata MojObject metadata; err = metadata.put("accountId", m_accountId); ErrorToException(err); builder.SetMetadata(metadata); }
void SmtpActivityFactory::BuildOutboxWatch(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId) { ActivityBuilder actBuilder; MojString name; name.format(OUTBOX_WATCH_ACTIVITY_FMT, AsJsonString(accountId).c_str()); ab.SetName(name); ab.SetDescription("Watches SMTP outbox for new emails"); ab.SetPersist(true); ab.SetExplicit(true); ab.SetRequiresInternet(false); // don't trigger until we also have connectivity ab.SetImmediate(true, ActivityBuilder::PRIORITY_LOW); // Callback MojObject callbackParams; MojErr err = callbackParams.put("accountId", accountId); ErrorToException(err); err = callbackParams.put("folderId", folderId); ErrorToException(err); ab.SetCallback(OUTBOX_BUS_METHOD, callbackParams); ab.SetMetadata(callbackParams); }
void ActivityBuilderFactory::BuildDeleteEmailsWatch(ActivityBuilder& builder) { MojString name; GetDeleteEmailsActivityName(name); MojString desc; GetDeleteEmailsActivityDesc(desc); builder.SetName(name.data()); builder.SetDescription(desc.data()); builder.SetPersist(true); builder.SetExplicit(true); builder.SetImmediate(true, "low"); // setup trigger MojDbQuery trigger; MojErr err = trigger.from(PopEmailAdapter::POP_EMAIL_KIND); ErrorToException(err); err = trigger.where("_del", MojDbQuery::OpEq, true); ErrorToException(err); builder.SetDatabaseWatchTrigger(trigger); // setup parameters (to be sent when trigger is called) MojObject params; err = params.put(PopFolderAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); builder.SetCallback(DELETE_EMAILS_CALLBACK, params); // put accountId in metadata MojObject metadata; err = metadata.put(PopFolderAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); builder.SetMetadata(metadata); }
void ImapActivityFactory::BuildScheduledSync(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, int seconds, bool requireFair) { MojErr err; ab.SetName( GetScheduledSyncName(accountId, folderId) ); MojString desc; err = desc.format("Scheduled sync every %d minutes", seconds/60); ErrorToException(err); ab.SetDescription(desc.data()); ab.SetExplicit(true); ab.SetPersist(true); ab.SetImmediate(true, "low"); SetNetworkRequirements(ab, requireFair); // Metadata MojObject metadata; SetMetadata(metadata, SCHEDULED_SYNC_NAME, accountId, folderId); ab.SetMetadata(metadata); // Wakeup ab.SetSyncInterval(0, seconds); // Callback MojObject params; err = params.put("accountId", accountId); ErrorToException(err); ab.SetCallback(SCHEDULED_SYNC_CALLBACK, params); }
void ActivityBuilderFactory::BuildAccountPrefsWatch(ActivityBuilder& builder, MojObject& accountRev) { MojString name; GetAccountPrefsWatchActivityName(name); MojString desc; GetAccountPrefsWatchActivityDesc(desc); builder.SetName(name.data()); builder.SetDescription(desc.data()); builder.SetPersist(true); builder.SetExplicit(true); builder.SetImmediate(true, "low"); MojDbQuery trigger; MojErr err = trigger.from(PopAccountAdapter::POP_ACCOUNT_KIND); ErrorToException(err); err = trigger.where(PopAccountAdapter::ACCOUNT_ID, MojDbQuery::OpEq, m_accountId); ErrorToException(err); err = trigger.where("_revPop", MojDbQuery::OpGreaterThan, accountRev); ErrorToException(err); builder.SetDatabaseWatchTrigger(trigger); MojObject params; err = params.put(PopAccountAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); builder.SetCallback(ACCOUNT_PREFS_WATCH_CALLBACK, params); MojObject metadata; err = metadata.put(PopAccountAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); builder.SetMetadata(metadata); }
void SmtpSyncOutboxCommand::UpdateAccountWatchActivity() { MojLogInfo(m_log, "UpdatingAccountWatchActivity"); try { // accoundId json object MojString accountIdJson; MojErr err = m_accountId.toJson(accountIdJson); ErrorToException(err); SmtpActivityFactory factory; ActivityBuilder ab; factory.BuildSmtpConfigWatch(ab, m_accountId, m_accountRev); bool updating = m_accountWatchActivity.get(); // and either update and complete the updated activity if we had adopted it, or re-create it. if ( updating ) { MojLogInfo(m_log, "updating account watch activity"); m_accountWatchActivity->SetSlots(m_accountActivityUpdatedSlot, m_accountActivityErrorSlot); m_accountWatchActivity->UpdateAndComplete(m_client, ab.GetActivityObject()); } else { // Create payload MojObject payload; err = payload.put("activity", ab.GetActivityObject()); ErrorToException(err); err = payload.put("start", true); ErrorToException(err); err = payload.put("replace", true); ErrorToException(err); MojLogInfo(m_log, "creating account watch activity"); m_client.SendRequest(m_createAccountWatchActivityResponseSlot, "com.palm.activitymanager", "create", payload); } } catch (std::exception & e) { HandleException(e, __func__); } catch (...) { HandleException(__func__); } }
void ImapActivityFactory::BuildStartIdle(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId) { MojErr err; ab.SetName( GetStartIdleName(accountId, folderId) ); ab.SetDescription("Starts a push connection when the network is available"); ab.SetExplicit(false); ab.SetPersist(true); ab.SetImmediate(true, "low"); SetNetworkRequirements(ab, false); // Metadata MojObject metadata; SetMetadata(metadata, MAINTAIN_IDLE_NAME, accountId, folderId); ab.SetMetadata(metadata); // Callback MojObject params; err = params.put("accountId", accountId); ErrorToException(err); err = params.put("folderId", folderId); ErrorToException(err); ab.SetCallback(MAINTAIN_IDLE_CALLBACK, params); }
void ImapActivityFactory::BuildPreferencesWatch(ActivityBuilder& ab, const MojObject& accountId, MojInt64 rev) { MojErr err; ab.SetName( GetPreferencesWatchName(accountId) ); ab.SetDescription("IMAP account preferences watch"); ab.SetPersist(true); ab.SetForeground(true); // Metadata MojObject metadata; SetMetadata(metadata, PREFS_WATCH_NAME, accountId); ab.SetMetadata(metadata); MojDbQuery trigger; err = trigger.from(ImapAccountAdapter::SCHEMA); ErrorToException(err); err = trigger.where(ImapAccountAdapter::ACCOUNT_ID, MojDbQuery::OpEq, accountId); ErrorToException(err); err = trigger.where(ImapAccountAdapter::CONFIG_REV, MojDbQuery::OpGreaterThan, rev); ErrorToException(err); ab.SetDatabaseWatchTrigger(trigger); MojObject params; err = params.put("accountId", accountId); ErrorToException(err); ab.SetCallback(PREFS_WATCH_CALLBACK, params); }
void NetworkStatusMonitor::CreateActivity() { ActivityBuilder ab; static MojInt64 uniqueId = 0; string serviceName = m_busClient.GetServiceName(); // FIXME if(serviceName.empty()) { throw MailException("no service name", __FILE__, __LINE__); } MojString name; MojErr err = name.format("%s network status check - %lld", serviceName.c_str(), ++uniqueId); ErrorToException(err); ab.SetName(name.data()); ab.SetDescription("Monitors network status"); ab.SetExplicit(false); ab.SetPersist(false); ab.SetForeground(true); ab.SetRequiresInternet(true); m_activity = Activity::PrepareNewActivity(ab, true, true); m_activity->SetSlots(m_activityUpdateSlot, m_activityErrorSlot); m_activity->Create(m_busClient); }
void ScheduleRetryCommand::ScheduleRetry() { CommandTraceFunction(); ImapActivityFactory factory; ActivityBuilder ab; // Get current retry interval from account EmailAccount::RetryStatus retryStatus = m_client.GetAccount().GetRetry(); int interval = retryStatus.GetInterval(); if(interval < INITIAL_RETRY_SECONDS) { interval = INITIAL_RETRY_SECONDS; } else if(interval < SECOND_RETRY_SECONDS) { interval = SECOND_RETRY_SECONDS; } else if(interval >= MAX_RETRY_SECONDS) { interval = MAX_RETRY_SECONDS; } else { // TODO: only update this on actual retry? interval *= RETRY_MULTIPLIER; } // Update account just in case it wasn't within the limit retryStatus.SetInterval(interval); retryStatus.SetCount(retryStatus.GetCount() + 1); m_client.GetAccount().SetRetry(retryStatus); factory.BuildSyncRetry(ab, m_client.GetAccountId(), m_folderId, interval, m_reason); MojErr err; MojObject payload; err = payload.put("activity", ab.GetActivityObject()); ErrorToException(err); err = payload.put("start", true); ErrorToException(err); err = payload.put("replace", true); MojLogInfo(m_log, "scheduling retry in %.1f minutes for account %s", float(interval) / 60, m_client.GetAccountIdString().c_str()); m_client.SendRequest(m_scheduleRetrySlot, "com.palm.activitymanager", "create", payload); }
void SmtpAccountEnableCommand::CreateSmtpConfigWatch() { SmtpActivityFactory factory; ActivityBuilder ab; factory.BuildSmtpConfigWatch(ab, m_client.GetAccountId(), m_accountRev); // Create payload MojObject payload; MojErr err; err = payload.put("activity", ab.GetActivityObject()); ErrorToException(err); err = payload.put("start", true); ErrorToException(err); err = payload.put("replace", true); ErrorToException(err); m_client.SendRequest(m_createSmtpConfigWatchSlot, "com.palm.activitymanager", "create", payload); }
void UpdateAccountCommand::UpdatePreferencesWatchActivity(MojInt64 rev) { CommandTraceFunction(); ImapActivityFactory factory; ActivityBuilder ab; MojLogInfo(m_log, "account %s preferences watch updated; rev=%lld", AsJsonString(m_accountId).c_str(), rev); if(rev > 0) { factory.BuildPreferencesWatch(ab, m_accountId, rev); m_activitySet->ReplaceActivity(ab.GetName(), ab.GetActivityObject()); } else { MojLogCritical(m_log, "unknown preferences rev (couldn't load account?); can't create watch"); m_activitySet->SetEndAction(Activity::EndAction_Complete); } m_activitySet->EndActivities(m_endActivitiesSlot); }
void ImapActivityFactory::BuildIdleWakeup(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, int seconds) { ab.SetName( GetIdleWakeupName(accountId, folderId) ); ab.SetDescription("Wakes up idle connection"); ab.SetExplicit(false); // goes away after a cancel ab.SetPersist(false); ab.SetForeground(true); // must run immediately ab.SetPowerOptions(false, true); // Wakeup ab.SetStartDelay(seconds); }
void SmtpActivityFactory::BuildSmtpConfigWatch(ActivityBuilder& ab, const MojObject& accountId, MojInt64 rev) { MojErr err; MojString name; err = name.format(ACCOUNT_WATCH_ACTIVITY_FMT, AsJsonString(accountId).c_str()); ErrorToException(err); // description of watch MojString desc; err = desc.format("Watches SMTP config on account %s", AsJsonString(accountId).c_str()); ErrorToException(err); // activity to setup watch ab.SetName(name); ab.SetDescription(desc.data()); ab.SetPersist(true); ab.SetExplicit(true); ab.SetRequiresInternet(false); // trigger even if we don't have a network connection ab.SetImmediate(true, ActivityBuilder::PRIORITY_LOW); // setup trigger // NOTE: how to trigger only on SMTP config change? MojDbQuery trigger; err = trigger.from("com.palm.mail.account:1"); ErrorToException(err); err = trigger.where("accountId", MojDbQuery::OpEq, accountId); ErrorToException(err); if (rev > 0) { trigger.where("_revSmtp", MojDbQuery::OpGreaterThan, rev); } ab.SetDatabaseWatchTrigger(trigger); MojObject params; err = params.put("accountId", accountId); ErrorToException(err); ab.SetCallback(ACCOUNT_UPDATED_BUS_METHOD, params); ab.SetMetadata(params); }
void ImapActivityFactory::BuildSyncRetry(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, int seconds, const std::string& reason) { MojErr err; ab.SetName( GetSyncRetryName(accountId, folderId) ); MojString desc; err = desc.format("Retry sync after %d seconds", seconds); ErrorToException(err); ab.SetDescription(desc.data()); ab.SetExplicit(true); ab.SetPersist(true); ab.SetImmediate(true, "low"); SetNetworkRequirements(ab, seconds <= 5 * 60); // Metadata MojObject metadata; SetMetadata(metadata, SYNC_RETRY_NAME, accountId, folderId); ab.SetMetadata(metadata); // Wakeup ab.SetSyncInterval(seconds, 0); // Callback MojObject params; err = params.put("accountId", accountId); ErrorToException(err); err = params.put("folderId", folderId); ErrorToException(err); MojObject retry; if(!reason.empty()) { err = retry.putString("reason", reason.c_str()); ErrorToException(err); } err = retry.put("interval", seconds); ErrorToException(err); err = params.put("retry", retry); ErrorToException(err); ab.SetCallback(SYNC_RETRY_CALLBACK, params); }
void ActivityBuilderFactory::BuildFolderRetrySync(ActivityBuilder &builder, const MojObject& folderId, int currInterval) { // activity to setup watch MojString name; GetFolderRetrySyncActivityName(name, folderId); // description of watch MojString desc; GetFolderRetrySyncActivityDesc(desc, folderId); // retry interval in seconds int nextRetryInterval = GetNextRetryIntervalMins(currInterval); int intervalSecs = MinsToSecs(nextRetryInterval); builder.SetName(name.data()); builder.SetDescription(desc.data()); builder.SetPersist(true); builder.SetExplicit(true); builder.SetRequiresInternet(false); builder.SetImmediate(true, "low"); builder.SetSyncInterval(0, intervalSecs); // setup parameters (to be sent when trigger is called) MojObject params; MojErr err = params.put(PopAccountAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); err = params.put("folderId", folderId); ErrorToException(err); err = params.put("lastRetryInterval", nextRetryInterval); ErrorToException(err); builder.SetCallback(FOLDER_RETRY_SYNC_CALLBACK, params); // put accountId in metadata MojObject metadata; err = metadata.put("accountId", m_accountId); ErrorToException(err); builder.SetMetadata(metadata); }
void ActivityBuilderFactory::BuildSentEmailsWatch(ActivityBuilder& builder, const MojObject& outboxFolderId, const MojObject& sentFolderId) { // activity to setup watch MojString name; GetSentEmailsWatchActivityName(name); // description of watch MojString desc; GetSentEmailsWatchActivityDesc(desc); builder.SetName(name.data()); builder.SetDescription(desc.data()); builder.SetPersist(true); builder.SetExplicit(true); builder.SetForeground(true); // setup trigger MojDbQuery trigger; MojErr err = trigger.from(EmailSchema::Kind::EMAIL); ErrorToException(err); err = trigger.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, outboxFolderId); ErrorToException(err); err = trigger.where("sendStatus.sent", MojDbQuery::OpEq, true); ErrorToException(err); builder.SetDatabaseWatchTrigger(trigger); // setup parameters (to be sent when trigger is called) MojObject params; err = params.put(PopFolderAdapter::ACCOUNT_ID, m_accountId); ErrorToException(err); err = params.put(PopFolderAdapter::OUTBOX_FOLDER_ID, outboxFolderId); ErrorToException(err); err = params.put(PopFolderAdapter::SENT_FOLDER_ID, sentFolderId); ErrorToException(err); builder.SetCallback(SENT_EMAILS_WATCH_CALLBACK, params); // put accountId in metadata MojObject metadata; err = metadata.put("accountId", m_accountId); ErrorToException(err); builder.SetMetadata(metadata); }
// This is used if we don't have any other activity to get network status from void ImapActivityFactory::BuildConnect(ActivityBuilder& ab, const MojObject& accountId, MojUInt64 uniqueId) { MojString name; MojErr err = name.format("%s - %lld", CONNECT_NAME, uniqueId); ErrorToException(err); ab.SetName( FormatName(name.data(), accountId) ); ab.SetDescription("Activity for connecting to server"); ab.SetExplicit(false); ab.SetPersist(false); ab.SetForeground(true); ab.SetRequiresInternet(false); }
void ImapActivityFactory::BuildFolderWatch(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, MojInt64 rev) { MojErr err; MojDbQuery query; ab.SetName( GetFolderWatchName(accountId, folderId) ); ab.SetDescription("Watches for updates to emails"); ab.SetExplicit(true); ab.SetPersist(true); SetNetworkRequirements(ab, true); ab.SetImmediate(true, "low"); // Metadata MojObject metadata; SetMetadata(metadata, FOLDER_WATCH_NAME, accountId, folderId); ab.SetMetadata(metadata); // Query err = query.from(ImapEmailAdapter::IMAP_EMAIL_KIND); ErrorToException(err); err = query.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId); ErrorToException(err); err = query.where(ImapEmailAdapter::UPSYNC_REV, MojDbQuery::OpGreaterThan, rev); ErrorToException(err); err = query.includeDeleted(true); ErrorToException(err); ab.SetDatabaseWatchTrigger(query); // Callback MojObject callbackParams; err = callbackParams.put("accountId", accountId); ErrorToException(err); err = callbackParams.put("folderId", folderId); ErrorToException(err); ab.SetCallback(FOLDER_WATCH_CALLBACK, callbackParams); }
void ImapActivityFactory::BuildDraftsWatch(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, MojInt64 rev) { MojErr err; ab.SetName( GetDraftsWatchName(accountId, folderId) ); ab.SetDescription("Watches for updates to draft emails"); ab.SetPersist(true); ab.SetExplicit(true); ab.SetForeground(true); // Metadata MojObject metadata; SetMetadata(metadata, DRAFTS_WATCH_NAME, accountId, folderId); ab.SetMetadata(metadata); MojDbQuery query; err = query.from(EmailSchema::Kind::EMAIL); ErrorToException(err); err = query.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId); ErrorToException(err); MojString editedDraftFlag; editedDraftFlag.format("%s.%s", EmailSchema::FLAGS, EmailSchema::Flags::EDITEDDRAFT); err = query.where(editedDraftFlag.data(), MojDbQuery::OpEq, true); ErrorToException(err); ab.SetDatabaseWatchTrigger(query); // Callback MojObject callbackParams; err = callbackParams.put("accountId", accountId); ErrorToException(err); err = callbackParams.put("folderId", accountId); ErrorToException(err); ab.SetCallback(DRAFTS_WATCH_CALLBACK, callbackParams); }
void ImapActivityFactory::BuildOutboxWatch(ActivityBuilder& ab, const MojObject& accountId, const MojObject& folderId, MojInt64 rev) { MojErr err; ab.SetName( GetOutboxWatchName(accountId, folderId) ); ab.SetDescription("Watches for sent emails in outbox"); ab.SetPersist(true); ab.SetExplicit(true); ab.SetForeground(true); // Metadata MojObject metadata; SetMetadata(metadata, OUTBOX_WATCH_NAME, accountId, folderId); ab.SetMetadata(metadata); MojDbQuery query; err = query.from(EmailSchema::Kind::EMAIL); ErrorToException(err); err = query.where(EmailSchema::FOLDER_ID, MojDbQuery::OpEq, folderId); ErrorToException(err); // sendStatus.sent MojString sentProp; sentProp.format("%s.%s",EmailSchema::SEND_STATUS, EmailSchema::SendStatus::SENT); err = query.where(sentProp.data(), MojDbQuery::OpEq, true); ErrorToException(err); ab.SetDatabaseWatchTrigger(query); // Callback MojObject callbackParams; err = callbackParams.put("accountId", accountId); ErrorToException(err); ab.SetCallback(OUTBOX_WATCH_CALLBACK, callbackParams); }
void SmtpSyncOutboxCommand::CheckNetworkConnectivity() { try { if (m_networkStatus->IsKnown()) { if (m_networkStatus->IsConnected()) { MojLogInfo(m_log, "CheckNetworkActivity: is connected, moving on"); GetAccount(); return; } else { MojLogInfo(m_log, "CheckNetworkActivity: is not connected, erroring out"); // Note that this account error explicitly doesn't delay the retry, on the assumption // that the next activity will be blocked until the network is available. m_error.errorCode = MailError::NO_NETWORK; m_error.errorOnAccount = true; m_error.errorOnEmail = false; m_error.internalError = "No network available for outbox sync"; m_error.errorText = ""; CompleteAndUpdateActivities(); return; } } else { MojLogInfo(m_log, "CheckNetworkActivity: state unknown, starting new activity"); MojLogInfo(m_log, "OutboxSyncer creating new network activity"); ActivityBuilder ab; MojString name; MojErr err = name.format("SMTP Internal Outbox Sync Network Activity for account %s", AsJsonString(m_accountId).c_str()); ErrorToException(err); ab.SetName(name); ab.SetDescription("Activity representing SMTP Outbox Sync Network Monitor"); ab.SetForeground(true); ab.SetRequiresInternet(false); ab.SetImmediate(true, ActivityBuilder::PRIORITY_LOW); m_networkActivity = Activity::PrepareNewActivity(ab); m_networkActivity->SetSlots(m_networkActivityUpdatedSlot, m_networkActivityErrorSlot); m_networkActivity->Create(m_client); } } catch (std::exception & e) { HandleException(e, __func__); } catch (...) { HandleException(__func__); } }
void ImapSession::CommandComplete(Command* command) { m_commandManager->CommandComplete(command); if(m_reconnectRequested && m_state == State_OkToSync && m_commandManager->GetActiveCommandCount() == 0 && m_commandManager->GetPendingCommandCount() > 0) { // If requested (and no active commands), disconnect from the server after finishing this command MojLogInfo(m_log, "disconnecting and reconnecting to server"); Logout(); } else if(m_state == State_OkToSync && m_commandManager->GetPendingCommandCount() == 0 && m_commandManager->GetActiveCommandCount() == 0) { MojLogInfo(m_log, "no commands active or pending"); // Either disconnect or run IDLE command // TODO also check account settings if(IsValidId(m_folderId) && IsPushEnabled(m_folderId)) { m_shouldPush = CheckNetworkHealthForPush(); } else { m_shouldPush = false; } if(m_shouldPush) { //MojLogInfo(m_log, "running idle command for folderId %s", AsJsonString(m_folderId).c_str()); if(m_account->IsYahoo()) { m_idleCommand.reset(new IdleYahooCommand(*this, m_folderId)); m_idleMode = IdleMode_YahooPush; } else { m_idleCommand.reset(new IdleCommand(*this, m_folderId)); m_idleMode = IdleMode_IDLE; } // Create activity to maintain idle. // If the device is rebooted or IMAP crashes, the callback will restart idle. // The activity will get cancelled if the connection goes into retry mode. if(true) { ImapActivityFactory factory; ActivityBuilder ab; factory.BuildStartIdle(ab, m_client->GetAccountId(), m_folderId); // Create new activity only if one doesn't already exist if(GetActivitySet()->FindActivityByName(ab.GetName()).get() == NULL) { ActivityPtr activity = Activity::PrepareNewActivity(ab, true, true); activity->SetName(ab.GetName()); activity->SetEndAction(Activity::EndAction_Complete); activity->SetEndOrder(Activity::EndOrder_Last); GetActivitySet()->AddActivity(activity); // Start activity right away activity->Create(*m_client); } } m_idleStartTime = 0; SetState(State_PreparingToIdle); m_commandManager->RunCommand(m_idleCommand); } else if(GetNoopIdleTimeout() > 0) { // TODO: this code is currently disabled MojLogInfo(m_log, "running NOOP idle command"); m_idleCommand.reset(new NoopIdleCommand(*this, m_folderId, GetNoopIdleTimeout())); m_idleMode = IdleMode_NOOP; m_idleStartTime = 0; // Reset flag m_recentUserInteraction = false; SetState(State_PreparingToIdle); m_commandManager->RunCommand(m_idleCommand); } else { if(IsPushRequested(m_folderId) && !m_shouldPush) { MojLogInfo(m_log, "setting up scheduled sync instead of push"); // If we can't push, set up a scheduled sync ImapActivityFactory factory; ActivityBuilder ab; factory.BuildScheduledSync(ab, m_client->GetAccountId(), m_folderId, FALLBACK_SYNC_INTERVAL, false); GetActivitySet()->ReplaceActivity(ab.GetName(), ab.GetActivityObject()); } else { MojLogInfo(m_log, "nothing left to do; disconnecting"); } Logout(); } } else if(m_state == State_Disconnecting && m_commandManager->GetActiveCommandCount() == 0) { Disconnected(); } }