Compress html and text content

This commit is contained in:
Maurice Parker 2021-02-24 15:14:38 -06:00
parent 680140baf2
commit 42930371b8
2 changed files with 78 additions and 16 deletions

View File

@ -25,6 +25,8 @@ final class CloudKitArticlesZone: CloudKitZone {
weak var database: CKDatabase?
var delegate: CloudKitZoneDelegate? = nil
var compressionQueue = DispatchQueue(label: "Articles Zone Compression Queue")
struct CloudKitArticle {
static let recordType = "Article"
struct Fields {
@ -33,7 +35,9 @@ final class CloudKitArticlesZone: CloudKitZone {
static let uniqueID = "uniqueID"
static let title = "title"
static let contentHTML = "contentHTML"
static let contentHTMLData = "contentHTMLData"
static let contentText = "contentText"
static let contentTextData = "contentTextData"
static let url = "url"
static let externalURL = "externalURL"
static let summary = "summary"
@ -96,7 +100,11 @@ final class CloudKitArticlesZone: CloudKitZone {
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)) {
@ -131,21 +139,28 @@ final class CloudKitArticlesZone: CloudKitZone {
}
}
self.modify(recordsToSave: modifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
switch result {
case .success:
self.saveIfNew(newRecords) { result in
switch result {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
compressionQueue.async {
self.compressArticleRecords(modifyRecords) { compressedModifyRecords in
self.compressArticleRecords(newRecords) { compressedNewRecords in
self.modify(recordsToSave: compressedModifyRecords, recordIDsToDelete: deleteRecordIDs) { result in
switch result {
case .success:
self.saveIfNew(compressedNewRecords) { result in
switch result {
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
}
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?
var database: SyncDatabase
weak var articlesZone: CloudKitArticlesZone?
var compressionQueue = DispatchQueue(label: "Articles Zone Delegate Compression Queue")
init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone) {
self.account = account
@ -134,7 +135,7 @@ private extension CloudKitArticlesZoneDelegate {
}
group.enter()
DispatchQueue.global(qos: .utility).async {
compressionQueue.async {
let parsedItems = records.compactMap { self.makeParsedItem($0) }
let webFeedIDsAndItems = Dictionary(grouping: parsedItems, by: { item in item.feedURL } ).mapValues { Set($0) }
@ -199,6 +200,20 @@ private extension CloudKitArticlesZoneDelegate {
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,
uniqueID: uniqueID,
feedURL: webFeedURL,
@ -206,8 +221,8 @@ private extension CloudKitArticlesZoneDelegate {
externalURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.externalURL] as? String,
title: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.title] as? String,
language: nil,
contentHTML: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTML] as? String,
contentText: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentText] as? String,
contentHTML: contentHTML,
contentText: contentText,
summary: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.summary] as? String,
imageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,
bannerImageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,