Realm file management


#1

We have been using Realm for a while and some of our users have been experiencing some data loss related to Realm. We think we have narrowed it down to our compaction method for when the file gets too big. We would like to ask for a little advice on if this is the proper way to recreate our Realm file. This method is called on applicationDidEnterBackground.

We wrote a sample of what we are doing below:

public static func compact() {
        // Get the original file path
        let configuration = RealmSampleClient.shared.config
        guard let originalFileURL = configuration.fileURL else {
            return
        }
        // check if the file size is bigger than 10mb, if not return
        guard let attr = try? FileManager.default.attributesOfItem(atPath: originalFileURL.absoluteString),
            let fileSize = attr[FileAttributeKey.size] as? UInt64,
            fileSize > 500_000_000 else {
                return
        }

         // create a filepath for a copy
        let date = Date()
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyyMMddHHmmss"
        let dateString = "\(dateFormatter.string(from: date)).realm"
        let copyFileURL = originalFileURL.deletingLastPathComponent().appendingPathComponent(dateString)

         // copy the Realm file
        do {
            let realm = try Realm(configuration: configuration)
            try realm.writeCopy(toFile: copyFileURL, encryptionKey: configuration.encryptionKey)
        } catch {
            return
        }

         // remove the old file and copy the new one
        do {
            removeRealmFile(at: originalFileURL)
            try FileManager.default.copyItem(at: copyFileURL, to: originalFileURL)
        } catch {
        }
        // remove a copy if it exists
        guard FileManager.default.fileExists(atPath: copyFileURL.path) else { return }
        do {
            try FileManager.default.removeItem(at: copyFileURL)
        } catch {
        }
    }

private static func removeRealmFile(at url: URL = databaseUrl) {
            let realmURLs = [
                url,
                url.appendingPathExtension("lock"),
                url.appendingPathExtension("note"),
                url.appendingPathExtension("management"),
            ]
            realmURLs.forEach { URL in
                guard FileManager.default.fileExists(atPath: URL.path) else { return }
                do {
                    try FileManager.default.removeItem(at: URL)
                } catch {
                }
            }
    }

Thanks for your help.