Merge pull request #1995 from kielgillard/ios-release
Feedly: renew access token once a day
This commit is contained in:
commit
059582c625
|
@ -23,6 +23,7 @@ final class AccountMetadata: Codable {
|
|||
case lastArticleFetchStartTime = "lastArticleFetch"
|
||||
case lastArticleFetchEndTime
|
||||
case endpointURL
|
||||
case lastCredentialRenewTime = "lastCredentialRenewTime"
|
||||
}
|
||||
|
||||
var name: String? {
|
||||
|
@ -81,6 +82,16 @@ final class AccountMetadata: Codable {
|
|||
}
|
||||
}
|
||||
|
||||
/// The last moment an account successfully renewed its credentials, or `nil` if no such moment exists.
|
||||
/// An account delegate can use this value to decide when to next ask the service provider to renew credentials.
|
||||
var lastCredentialRenewTime: Date? {
|
||||
didSet {
|
||||
if lastCredentialRenewTime != oldValue {
|
||||
valueDidChange(.lastCredentialRenewTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
weak var delegate: AccountMetadataDelegate?
|
||||
|
||||
func valueDidChange(_ key: CodingKeys) {
|
||||
|
|
|
@ -111,11 +111,20 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
let log = self.log
|
||||
let operation = FeedlySyncAllOperation(account: account, credentials: credentials, caller: caller, database: database, lastSuccessfulFetchStartDate: accountMetadata?.lastArticleFetchStartTime, downloadProgress: refreshProgress, log: log)
|
||||
|
||||
operation.downloadProgress = refreshProgress
|
||||
let refreshAccessToken = FeedlyRefreshAccessTokenOperation(account: account, service: self, oauthClient: oauthAuthorizationClient, refreshDate: Date(), log: log)
|
||||
refreshAccessToken.downloadProgress = refreshProgress
|
||||
operationQueue.add(refreshAccessToken)
|
||||
|
||||
let syncAllOperation = FeedlySyncAllOperation(account: account, feedlyUserId: credentials.username, caller: caller, database: database, lastSuccessfulFetchStartDate: accountMetadata?.lastArticleFetchStartTime, downloadProgress: refreshProgress, log: log)
|
||||
|
||||
syncAllOperation.downloadProgress = refreshProgress
|
||||
|
||||
// Ensure the sync uses the latest credential.
|
||||
syncAllOperation.addDependency(refreshAccessToken)
|
||||
|
||||
let date = Date()
|
||||
operation.syncCompletionHandler = { [weak self] result in
|
||||
syncAllOperation.syncCompletionHandler = { [weak self] result in
|
||||
if case .success = result {
|
||||
self?.accountMetadata?.lastArticleFetchStartTime = date
|
||||
self?.accountMetadata?.lastArticleFetchEndTime = Date()
|
||||
|
@ -125,9 +134,9 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||
completion(result)
|
||||
}
|
||||
|
||||
currentSyncAllOperation = operation
|
||||
currentSyncAllOperation = syncAllOperation
|
||||
|
||||
operationQueue.add(operation)
|
||||
operationQueue.add(syncAllOperation)
|
||||
}
|
||||
|
||||
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
|
@ -155,7 +164,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||
|
||||
let group = DispatchGroup()
|
||||
|
||||
let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: caller, database: database, newerThan: nil, log: log)
|
||||
let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: caller, database: database, newerThan: nil, log: log)
|
||||
|
||||
group.enter()
|
||||
ingestUnread.completionBlock = { _ in
|
||||
|
@ -163,7 +172,7 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||
|
||||
}
|
||||
|
||||
let ingestStarred = FeedlyIngestStarredArticleIdsOperation(account: account, credentials: credentials, service: caller, database: database, newerThan: nil, log: log)
|
||||
let ingestStarred = FeedlyIngestStarredArticleIdsOperation(account: account, userId: credentials.username, service: caller, database: database, newerThan: nil, log: log)
|
||||
|
||||
group.enter()
|
||||
ingestStarred.completionBlock = { _ in
|
||||
|
@ -492,9 +501,6 @@ final class FeedlyAccountDelegate: AccountDelegate {
|
|||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
credentials = try? account.retrieveCredentials(type: .oauthAccessToken)
|
||||
|
||||
let refreshAccessToken = FeedlyRefreshAccessTokenOperation(account: account, service: self, oauthClient: oauthAuthorizationClient, log: log)
|
||||
operationQueue.add(refreshAccessToken)
|
||||
}
|
||||
|
||||
func accountWillBeDeleted(_ account: Account) {
|
||||
|
|
|
@ -89,7 +89,7 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
|||
createFeeds.downloadProgress = downloadProgress
|
||||
operationQueue.add(createFeeds)
|
||||
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: syncUnreadIdsService, database: database, newerThan: nil, log: log)
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: syncUnreadIdsService, database: database, newerThan: nil, log: log)
|
||||
syncUnread.addDependency(createFeeds)
|
||||
syncUnread.downloadProgress = downloadProgress
|
||||
syncUnread.delegate = self
|
||||
|
|
|
@ -29,8 +29,8 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
|||
self.log = log
|
||||
}
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamIdsService, newerThan: Date?, log: OSLog) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: credentials.username)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, newerThan: Date?, log: OSLog) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
self.init(account: account, resource: all, service: service, newerThan: newerThan, log: log)
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation {
|
|||
private var remoteEntryIds = Set<String>()
|
||||
private let log: OSLog
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?, log: OSLog) {
|
||||
let resource = FeedlyTagResourceId.Global.saved(for: credentials.username)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?, log: OSLog) {
|
||||
let resource = FeedlyTagResourceId.Global.saved(for: userId)
|
||||
self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan, log: log)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation {
|
|||
self.log = log
|
||||
}
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamIdsService, log: OSLog) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: credentials.username)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, log: OSLog) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
self.init(account: account, resource: all, service: service, log: log)
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation {
|
|||
private var remoteEntryIds = Set<String>()
|
||||
private let log: OSLog
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?, log: OSLog) {
|
||||
let resource = FeedlyCategoryResourceId.Global.all(for: credentials.username)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?, log: OSLog) {
|
||||
let resource = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan, log: log)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,14 +17,32 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
|||
let account: Account
|
||||
let log: OSLog
|
||||
|
||||
init(account: Account, service: OAuthAccessTokenRefreshing, oauthClient: OAuthAuthorizationClient, log: OSLog) {
|
||||
/// The moment the refresh is being requested. The token will refresh only if the account's `lastCredentialRenewTime` is not on the same day as this moment. When nil, the operation will always refresh the token.
|
||||
let refreshDate: Date?
|
||||
|
||||
init(account: Account, service: OAuthAccessTokenRefreshing, oauthClient: OAuthAuthorizationClient, refreshDate: Date?, log: OSLog) {
|
||||
self.oauthClient = oauthClient
|
||||
self.service = service
|
||||
self.account = account
|
||||
self.refreshDate = refreshDate
|
||||
self.log = log
|
||||
}
|
||||
|
||||
override func run() {
|
||||
// Only refresh the token if these dates are not on the same day.
|
||||
let shouldRefresh: Bool = {
|
||||
guard let date = refreshDate, let lastRenewDate = account.metadata.lastCredentialRenewTime else {
|
||||
return true
|
||||
}
|
||||
return !Calendar.current.isDate(lastRenewDate, equalTo: date, toGranularity: .day)
|
||||
}()
|
||||
|
||||
guard shouldRefresh else {
|
||||
os_log(.debug, log: log, "Skipping access token renewal.")
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
let refreshToken: Credentials
|
||||
|
||||
do {
|
||||
|
@ -64,6 +82,8 @@ final class FeedlyRefreshAccessTokenOperation: FeedlyOperation {
|
|||
// Now store the access token because we want the account delegate to use it.
|
||||
try account.storeCredentials(grant.accessToken)
|
||||
|
||||
account.metadata.lastCredentialRenewTime = Date()
|
||||
|
||||
didFinish()
|
||||
} catch {
|
||||
didFinish(with: error)
|
||||
|
|
|
@ -33,7 +33,7 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
///
|
||||
/// Download articles for statuses at the union of those statuses without its corresponding article and those included in 3 (changed since last successful sync).
|
||||
///
|
||||
init(account: Account, credentials: Credentials, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIdsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIdsService, getStreamIdsService: FeedlyGetStreamIdsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress, log: OSLog) {
|
||||
init(account: Account, feedlyUserId: String, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIdsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIdsService, getStreamIdsService: FeedlyGetStreamIdsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress, log: OSLog) {
|
||||
self.syncUUID = UUID()
|
||||
self.log = log
|
||||
self.operationQueue.suspend()
|
||||
|
@ -67,14 +67,14 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
createFeedsOperation.addDependency(mirrorCollectionsAsFolders)
|
||||
self.operationQueue.add(createFeedsOperation)
|
||||
|
||||
let getAllArticleIds = FeedlyIngestStreamArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, log: log)
|
||||
let getAllArticleIds = FeedlyIngestStreamArticleIdsOperation(account: account, userId: feedlyUserId, service: getStreamIdsService, log: log)
|
||||
getAllArticleIds.delegate = self
|
||||
getAllArticleIds.downloadProgress = downloadProgress
|
||||
getAllArticleIds.addDependency(createFeedsOperation)
|
||||
self.operationQueue.add(getAllArticleIds)
|
||||
|
||||
// Get each page of unread article ids in the global.all stream for the last 31 days (nil = Feedly API default).
|
||||
let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: getUnreadService, database: database, newerThan: nil, log: log)
|
||||
let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: feedlyUserId, service: getUnreadService, database: database, newerThan: nil, log: log)
|
||||
getUnread.delegate = self
|
||||
getUnread.addDependency(getAllArticleIds)
|
||||
getUnread.downloadProgress = downloadProgress
|
||||
|
@ -82,14 +82,14 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
|
||||
// Get each page of the article ids which have been update since the last successful fetch start date.
|
||||
// If the date is nil, this operation provides an empty set (everything is new, nothing is updated).
|
||||
let getUpdated = FeedlyGetUpdatedArticleIdsOperation(account: account, credentials: credentials, service: getStreamIdsService, newerThan: lastSuccessfulFetchStartDate, log: log)
|
||||
let getUpdated = FeedlyGetUpdatedArticleIdsOperation(account: account, userId: feedlyUserId, service: getStreamIdsService, newerThan: lastSuccessfulFetchStartDate, log: log)
|
||||
getUpdated.delegate = self
|
||||
getUpdated.downloadProgress = downloadProgress
|
||||
getUpdated.addDependency(createFeedsOperation)
|
||||
self.operationQueue.add(getUpdated)
|
||||
|
||||
// Get each page of the article ids for starred articles.
|
||||
let getStarred = FeedlyIngestStarredArticleIdsOperation(account: account, credentials: credentials, service: getStarredService, database: database, newerThan: nil, log: log)
|
||||
let getStarred = FeedlyIngestStarredArticleIdsOperation(account: account, userId: feedlyUserId, service: getStarredService, database: database, newerThan: nil, log: log)
|
||||
getStarred.delegate = self
|
||||
getStarred.downloadProgress = downloadProgress
|
||||
getStarred.addDependency(createFeedsOperation)
|
||||
|
@ -125,8 +125,8 @@ final class FeedlySyncAllOperation: FeedlyOperation {
|
|||
self.operationQueue.add(finishOperation)
|
||||
}
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, caller: FeedlyAPICaller, database: SyncDatabase, lastSuccessfulFetchStartDate: Date?, downloadProgress: DownloadProgress, log: OSLog) {
|
||||
self.init(account: account, credentials: credentials, lastSuccessfulFetchStartDate: lastSuccessfulFetchStartDate, markArticlesService: caller, getUnreadService: caller, getCollectionsService: caller, getStreamContentsService: caller, getStarredService: caller, getStreamIdsService: caller, getEntriesService: caller, database: database, downloadProgress: downloadProgress, log: log)
|
||||
convenience init(account: Account, feedlyUserId: String, caller: FeedlyAPICaller, database: SyncDatabase, lastSuccessfulFetchStartDate: Date?, downloadProgress: DownloadProgress, log: OSLog) {
|
||||
self.init(account: account, feedlyUserId: feedlyUserId, lastSuccessfulFetchStartDate: lastSuccessfulFetchStartDate, markArticlesService: caller, getUnreadService: caller, getCollectionsService: caller, getStreamContentsService: caller, getStarredService: caller, getStreamIdsService: caller, getEntriesService: caller, database: database, downloadProgress: downloadProgress, log: log)
|
||||
}
|
||||
|
||||
override func run() {
|
||||
|
|
Loading…
Reference in New Issue