Skip to content

Commit

Permalink
Merge pull request #127 from boostcampwm-2022/refactor/userUseCase
Browse files Browse the repository at this point in the history
Refactor/data & SyncManager
  • Loading branch information
jinwoong16 committed Dec 9, 2022
2 parents 881f878 + b68f9b2 commit 7fe3512
Show file tree
Hide file tree
Showing 36 changed files with 332 additions and 211 deletions.
4 changes: 4 additions & 0 deletions DailyQuest/DailyQuest.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
A5AC96DF292239CA003B7637 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = A5AC96DE292239CA003B7637 /* RealmSwift */; };
A5AC96E629223F06003B7637 /* QuestsStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5AC96E529223F06003B7637 /* QuestsStorage.swift */; };
A5AC96E829223F27003B7637 /* RealmQuestsStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5AC96E729223F27003B7637 /* RealmQuestsStorage.swift */; };
A5BD61E629423FBB0075970F /* SyncManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5BD61E529423FBB0075970F /* SyncManager.swift */; };
A5D3C813293DB1BE00F43B76 /* DataConfigure.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D3C812293DB1BE00F43B76 /* DataConfigure.swift */; };
A5D3C823293DDDAD00F43B76 /* ProtectedUserRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D3C822293DDDAD00F43B76 /* ProtectedUserRepository.swift */; };
A5D3C828293DDEBE00F43B76 /* QuestsRepositoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5D3C827293DDEBE00F43B76 /* QuestsRepositoryTests.swift */; };
Expand Down Expand Up @@ -383,6 +384,7 @@
A5AC96DB292237C3003B7637 /* QuestEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestEntity.swift; sourceTree = "<group>"; };
A5AC96E529223F06003B7637 /* QuestsStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestsStorage.swift; sourceTree = "<group>"; };
A5AC96E729223F27003B7637 /* RealmQuestsStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RealmQuestsStorage.swift; sourceTree = "<group>"; };
A5BD61E529423FBB0075970F /* SyncManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncManager.swift; sourceTree = "<group>"; };
A5D3C812293DB1BE00F43B76 /* DataConfigure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataConfigure.swift; sourceTree = "<group>"; };
A5D3C822293DDDAD00F43B76 /* ProtectedUserRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtectedUserRepository.swift; sourceTree = "<group>"; };
A5D3C827293DDEBE00F43B76 /* QuestsRepositoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestsRepositoryTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -919,6 +921,7 @@
34ACC32E291DE9C000741371 /* SceneDelegate.swift */,
34A529D429247932001BAD34 /* AppCoordinator.swift */,
34A529E829248B58001BAD34 /* AppAppearance.swift */,
A5BD61E529423FBB0075970F /* SyncManager.swift */,
);
path = Application;
sourceTree = "<group>";
Expand Down Expand Up @@ -1425,6 +1428,7 @@
34FCD36B293DF2F600E0DC8A /* FriendStatusView.swift in Sources */,
A51F01CA2923397E0031ECA2 /* UserInfoEntity.swift in Sources */,
345687F42937329E00CA51E3 /* EnrollViewController.swift in Sources */,
A5BD61E629423FBB0075970F /* SyncManager.swift in Sources */,
A511229029384FAF00384B4B /* DefaultUserRepository.swift in Sources */,
A5003ABB293F914500082A9C /* DefaultUserUseCase.swift in Sources */,
342830FF292E2B2A00AE811B /* NavigateCell.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions DailyQuest/DailyQuest/Application/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.

let syncManager = SyncManager()
syncManager.sync()
}


Expand Down
82 changes: 82 additions & 0 deletions DailyQuest/DailyQuest/Application/SyncManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//
// SyncManager.swift
// DailyQuest
//
// Created by 이전희 on 2022/12/09.
//

import UIKit
import RxSwift

final class SyncManager {
private let app = UIApplication.shared
private let persistentStorage: RealmStorage = RealmStorage.shared
private let networkStorage: NetworkService = FirebaseService.shared

private let disposeBag = DisposeBag()

func sync(){
guard FirebaseService.shared.uid.value != nil else {return }
let taskId = app.beginBackgroundTask()
self.qusetsSync()
.timeout(.seconds(20), scheduler: MainScheduler.instance)
.subscribe(onSuccess:{ res in
print("",res)
self.app.endBackgroundTask(taskId)
},onFailure: { error in
print("",error)
self.app.endBackgroundTask(taskId)
}, onDisposed: {
print("disposed")
})
.disposed(by: disposeBag)
}

private func qusetsSync() -> Single<Bool> {
self.fetchQuests()
.flatMap { [weak self] persistentStorageQuest in
guard let self = self else { return Single<[Quest]>.just([]) }
return self.networkStorage.read(type: QuestDTO.self, userCase: .currentUser, access: .quests, filter: nil)
.map { $0.toDomain() }
.toArray()
.map { networkServiceQuests in
let networkServiceQuestsDict = Dictionary(uniqueKeysWithValues: networkServiceQuests.map { ($0.uuid, $0) })
let quests = persistentStorageQuest.filter {
guard let dictQuest = networkServiceQuestsDict[$0.uuid] else { return true }
return dictQuest != $0
}
return quests
}
}
.flatMap{ [weak self] syncQuests in
guard let self = self else { return Single<Bool>.just(false)}
return Observable<Quest>.from(syncQuests)
.flatMap { quest in
self.networkStorage.create(userCase: .currentUser, access: .quests, dto: quest.toDTO())
}
.map{$0.toDomain()}
.toArray()
.map{ _ in true}
}
}

private func fetchQuests() -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let persistentStorage = self?.persistentStorage else {
single(.failure(RealmStorageError.noDataError))
return Disposables.create()
}

do {
let quests = try persistentStorage
.fetchEntities(type: QuestEntity.self, filter: nil)
.compactMap { $0.toDomain() }
single(.success(quests))
} catch let error {
single(.failure(error))
}

return Disposables.create()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import RxSwift

protocol BrowseQuestsStorage {
func fetchBrowseQuests() -> Observable<[BrowseQuest]>
func fetchBrowseQuests() -> Single<[BrowseQuest]>
func saveBrowseQuest(browseQuest: BrowseQuest) -> Single<BrowseQuest>
func deleteBrowseQuests() -> Single<Bool>
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@ final class RealmBrowseQuestsStorage {
}

extension RealmBrowseQuestsStorage: BrowseQuestsStorage {
func fetchBrowseQuests() -> Observable<[BrowseQuest]> {
return Observable<[BrowseQuest]>.create { [weak self] observer in
func fetchBrowseQuests() -> Single<[BrowseQuest]> {
return Single<[BrowseQuest]>.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let browseQuests = try realmStorage.fetchEntities(type: BrowseQuestEntity.self)
.compactMap { $0.toDomain() }
observer.onNext(browseQuests)
observer.onCompleted()
single(.success(browseQuests))
} catch let error {
observer.onError(error)
single(.failure(error))
}

return Disposables.create()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import RxSwift

protocol QuestsStorage {
func saveQuests(with quests: [Quest]) -> Single<[Quest]>
func fetchQuests(by date: Date) -> Observable<[Quest]>
func fetchQuests(by date: Date) -> Single<[Quest]>
func updateQuest(with quest: Quest) -> Single<Quest>
func deleteQuest(with questId: UUID) -> Single<Quest>
func deleteQuestGroup(with groupId: UUID) -> Single<[Quest]>
func deleteAllQuests() -> Single<[Quest]>
func fetchQuests() -> Single<[Quest]>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import Foundation
import RxSwift

final class RealmQuestsStorage {

private let realmStorage: RealmStorage

init(realmStorage: RealmStorage = RealmStorage.shared) {
self.realmStorage = realmStorage
}
Expand All @@ -23,7 +23,6 @@ extension RealmQuestsStorage: QuestsStorage {
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
for quest in quests {
let questEntity = QuestEntity(quest: quest)
Expand All @@ -32,32 +31,28 @@ extension RealmQuestsStorage: QuestsStorage {
single(.success(quests))
} catch let error {
single(.failure(RealmStorageError.saveError(error)))

}
return Disposables.create()
}
}

func fetchQuests(by date: Date) -> Observable<[Quest]> {
return Observable<[Quest]>.create { [weak self] observer in
func fetchQuests(by date: Date) -> Single<[Quest]> {
return Single<[Quest]>.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let quests = try realmStorage
.fetchEntities(type: QuestEntity.self, filter: NSPredicate(format: "date == %@", date.toString))
.compactMap { $0.toDomain() }
observer.onNext(quests)
observer.onCompleted()
single(.success(quests))
} catch let error {
observer.onError(error)
single(.failure(error))
}

return Disposables.create()
}
}

func updateQuest(with quest: Quest) -> Single<Quest> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
Expand All @@ -68,60 +63,52 @@ extension RealmQuestsStorage: QuestsStorage {
try realmStorage.updateEntity(entity: questEntity)
single(.success(quest))
} catch let error {
print(#function)
print(error)
single(.failure(RealmStorageError.saveError(error)))
single(.failure(RealmStorageError.updateError(error)))
}

return Disposables.create()
}
}

func deleteQuest(with questId: UUID) -> Single<Quest> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
guard let entity = try realmStorage.findEntities(type: QuestEntity.self, filter: NSPredicate(format: "uuid == %@", questId as CVarArg)).first else {
throw RealmStorageError.noDataError
}
let quest = entity.toDomain()
try realmStorage.deleteEntity(entity: entity)
single(.success(quest))

} catch let error {
single(.failure(RealmStorageError.deleteError(error)))
}

return Disposables.create()
}

}

func deleteQuestGroup(with groupId: UUID) -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let entities = try realmStorage.findEntities(type: QuestEntity.self, filter: NSPredicate(format: "groupId == %@", groupId as CVarArg))
let quests = entities.compactMap { $0.toDomain() }
for entity in entities {
try realmStorage.deleteEntity(entity: entity)
}
single(.success(quests))

} catch let error {
single(.failure(RealmStorageError.deleteError(error)))
}

return Disposables.create()
}
}

func deleteAllQuests() -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
Expand All @@ -134,11 +121,29 @@ extension RealmQuestsStorage: QuestsStorage {
try realmStorage.deleteEntity(entity: entity)
}
single(.success(quests))

} catch let error {
single(.failure(RealmStorageError.deleteError(error)))
}


return Disposables.create()
}
}

func fetchQuests() -> Single<[Quest]> {
return Single.create { [weak self] single in
guard let realmStorage = self?.realmStorage else {
return Disposables.create()
}

do {
let quests = try realmStorage
.fetchEntities(type: QuestEntity.self, filter: nil)
.compactMap { $0.toDomain() }
single(.success(quests))
} catch let error {
single(.failure(error))
}

return Disposables.create()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import Foundation
enum RealmStorageError: Error {
case realmObjectError
case noDataError
case readError(Error)
case saveError(Error)
case readError(Error)
case updateError(Error)
case deleteError(Error)
}

Expand Down
Loading

0 comments on commit 7fe3512

Please sign in to comment.