Compress html and text content

This commit is contained in:
Maurice Parker 2021-02-24 15:14:38 -06:00
parent 947ceee7e7
commit a51bcc2f0e
2 changed files with 78 additions and 16 deletions

View File

@ -25,6 +25,8 @@ final class CloudKitArticlesZone: CloudKitZone {
weak var database: CKDatabase? weak var database: CKDatabase?
var delegate: CloudKitZoneDelegate? = nil var delegate: CloudKitZoneDelegate? = nil
var compressionQueue = DispatchQueue(label: "Articles Zone Compression Queue")
struct CloudKitArticle { struct CloudKitArticle {
static let recordType = "Article" static let recordType = "Article"
struct Fields { struct Fields {
@ -33,7 +35,9 @@ final class CloudKitArticlesZone: CloudKitZone {
static let uniqueID = "uniqueID" static let uniqueID = "uniqueID"
static let title = "title" static let title = "title"
static let contentHTML = "contentHTML" static let contentHTML = "contentHTML"
static let contentHTMLData = "contentHTMLData"
static let contentText = "contentText" static let contentText = "contentText"
static let contentTextData = "contentTextData"
static let url = "url" static let url = "url"
static let externalURL = "externalURL" static let externalURL = "externalURL"
static let summary = "summary" static let summary = "summary"
@ -96,7 +100,11 @@ final class CloudKitArticlesZone: CloudKitZone {
records.append(makeArticleRecord(saveArticle)) records.append(makeArticleRecord(saveArticle))
} }
save(records, completion: completion) compressionQueue.async {
self.compressArticleRecords(records) { compressedRecords in
self.save(compressedRecords, completion: completion)
}
}
} }
func deleteArticles(_ webFeedExternalID: String, completion: @escaping ((Result<Void, Error>) -> Void)) { func deleteArticles(_ webFeedExternalID: String, completion: @escaping ((Result<Void, Error>) -> Void)) {
@ -130,22 +138,29 @@ final class CloudKitArticlesZone: CloudKitZone {
deleteRecordIDs.append(CKRecord.ID(recordName: self.articleID(statusUpdate.articleID), zoneID: zoneID)) deleteRecordIDs.append(CKRecord.ID(recordName: self.articleID(statusUpdate.articleID), zoneID: zoneID))
} }
} }
self.modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in compressionQueue.async {
switch result { self.compressArticleRecords(modifyRecords) { compressedModifyRecords in
case .success: self.compressArticleRecords(newRecords) { compressedNewRecords in
self.saveIfNew(newRecords) { result in self.modify(recordsToSave: compressedModifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
switch result { switch result {
case .success: case .success:
completion(.success(())) self.saveIfNew(compressedNewRecords) { result in
case .failure(let error): switch result {
completion(.failure(error)) case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
}
}
case .failure(let error):
self.handleModifyArticlesError(error, statusUpdates: statusUpdates, completion: completion)
}
} }
} }
case .failure(let error):
self.handleModifyArticlesError(error, statusUpdates: statusUpdates, completion: completion)
} }
} }
} }
} }
@ -237,5 +252,37 @@ private extension CloudKitArticlesZone {
return record return record
} }
func compressArticleRecords(_ records: [CKRecord], completion: ([CKRecord]) -> Void ) {
var result = [CKRecord]()
for record in records {
if record.recordType == CloudKitArticle.recordType {
if let contentHTML = record[CloudKitArticle.Fields.contentHTML] as? String {
let data = Data(contentHTML.utf8) as NSData
if let compressedData = try? data.compressed(using: .lzfse) {
record[CloudKitArticle.Fields.contentHTMLData] = compressedData
record[CloudKitArticle.Fields.contentHTML] = nil
}
}
if let contentText = record[CloudKitArticle.Fields.contentText] as? String {
let data = Data(contentText.utf8) as NSData
if let compressedData = try? data.compressed(using: .lzfse) {
record[CloudKitArticle.Fields.contentTextData] = compressedData
record[CloudKitArticle.Fields.contentText] = nil
}
}
} else {
result.append(record)
}
}
completion(result)
}
} }

View File

@ -23,6 +23,7 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
weak var account: Account? weak var account: Account?
var database: SyncDatabase var database: SyncDatabase
weak var articlesZone: CloudKitArticlesZone? weak var articlesZone: CloudKitArticlesZone?
var compressionQueue = DispatchQueue(label: "Articles Zone Delegate Compression Queue")
init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone) { init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone) {
self.account = account self.account = account
@ -134,7 +135,7 @@ private extension CloudKitArticlesZoneDelegate {
} }
group.enter() group.enter()
DispatchQueue.global(qos: .utility).async { compressionQueue.async {
let parsedItems = records.compactMap { self.makeParsedItem($0) } let parsedItems = records.compactMap { self.makeParsedItem($0) }
let webFeedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) } let webFeedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) }
@ -199,6 +200,20 @@ private extension CloudKitArticlesZoneDelegate {
return nil return nil
} }
var contentHTML = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTML] as? String
if let contentHTMLData = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTMLData] as? NSData {
if let decompressedContentHTMLData = try? contentHTMLData.decompressed(using: .lzfse) {
contentHTML = String(data: decompressedContentHTMLData as Data, encoding: .utf8)
}
}
var contentText = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentText] as? String
if let contentTextData = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentTextData] as? NSData {
if let decompressedContentTextData = try? contentTextData.decompressed(using: .lzfse) {
contentText = String(data: decompressedContentTextData as Data, encoding: .utf8)
}
}
let parsedItem = ParsedItem(syncServiceID: nil, let parsedItem = ParsedItem(syncServiceID: nil,
uniqueID: uniqueID, uniqueID: uniqueID,
feedURL: webFeedURL, feedURL: webFeedURL,
@ -206,8 +221,8 @@ private extension CloudKitArticlesZoneDelegate {
externalURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.externalURL] as? String, externalURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.externalURL] as? String,
title: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.title] as? String, title: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.title] as? String,
language: nil, language: nil,
contentHTML: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTML] as? String, contentHTML: contentHTML,
contentText: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentText] as? String, contentText: contentText,
summary: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.summary] as? String, summary: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.summary] as? String,
imageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String, imageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,
bannerImageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String, bannerImageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,