1 package expo.modules.updates.db.dao 2 3 import androidx.room.* 4 import expo.modules.updates.db.entity.AssetEntity 5 import expo.modules.updates.db.entity.UpdateEntity 6 import expo.modules.updates.db.enums.UpdateStatus 7 import java.util.* 8 9 /** 10 * Utility class for accessing and modifying data in SQLite relating to updates. 11 */ 12 @Dao 13 abstract class UpdateDao { 14 /** 15 * for private use only 16 * must be marked public for Room 17 * so we use the underscore to discourage use 18 */ 19 20 // if an update has successfully launched at least once, we treat it as launchable 21 // even if it has also failed to launch at least once 22 @Query("SELECT * FROM updates WHERE scope_key = :scopeKey AND (successful_launch_count > 0 OR failed_launch_count < 1) AND status IN (:statuses);") _loadLaunchableUpdatesForProjectWithStatusesnull23 abstract fun _loadLaunchableUpdatesForProjectWithStatuses(scopeKey: String?, statuses: List<UpdateStatus>): List<UpdateEntity> 24 25 @Query("SELECT * FROM updates WHERE id = :id;") 26 abstract fun _loadUpdatesWithId(id: UUID): List<UpdateEntity> 27 28 @Query("SELECT assets.* FROM assets INNER JOIN updates ON updates.launch_asset_id = assets.id WHERE updates.id = :id;") 29 abstract fun _loadLaunchAsset(id: UUID): AssetEntity 30 31 @Query("UPDATE updates SET keep = 1 WHERE id = :id;") 32 abstract fun _keepUpdate(id: UUID) 33 34 @Query("UPDATE updates SET status = :status WHERE id = :id;") 35 abstract fun _markUpdateWithStatus(status: UpdateStatus, id: UUID) 36 37 @Query( 38 "UPDATE updates SET status = :status WHERE id IN (" + 39 "SELECT DISTINCT update_id FROM updates_assets WHERE asset_id IN (:missingAssetIds));" 40 ) 41 abstract fun _markUpdatesWithMissingAssets(missingAssetIds: List<Long>, status: UpdateStatus) 42 43 /** 44 * for public use 45 */ 46 @Query("SELECT * FROM updates;") 47 abstract fun loadAllUpdates(): List<UpdateEntity> 48 49 fun loadLaunchableUpdatesForScope(scopeKey: String?): List<UpdateEntity> { 50 return _loadLaunchableUpdatesForProjectWithStatuses( 51 scopeKey, 52 listOf(UpdateStatus.READY, UpdateStatus.EMBEDDED, UpdateStatus.DEVELOPMENT) 53 ) 54 } 55 56 @Query("SELECT * FROM updates WHERE status = :status;") loadAllUpdatesWithStatusnull57 abstract fun loadAllUpdatesWithStatus(status: UpdateStatus): List<UpdateEntity> 58 59 @Query("SELECT id FROM updates WHERE status = :status;") 60 abstract fun loadAllUpdateIdsWithStatus(status: UpdateStatus): List<UUID> 61 62 fun loadUpdateWithId(id: UUID): UpdateEntity? { 63 val updateEntities = _loadUpdatesWithId(id) 64 return if (updateEntities.isNotEmpty()) updateEntities[0] else null 65 } 66 loadLaunchAssetnull67 fun loadLaunchAsset(id: UUID): AssetEntity { 68 val assetEntity = _loadLaunchAsset(id) 69 assetEntity.isLaunchAsset = true 70 return assetEntity 71 } 72 73 @Insert insertUpdatenull74 abstract fun insertUpdate(update: UpdateEntity) 75 76 fun setUpdateScopeKey(update: UpdateEntity, newScopeKey: String) { 77 update.scopeKey = newScopeKey 78 _setUpdateScopeKeyInternal(update.id, newScopeKey) 79 } 80 81 @Query("UPDATE updates SET scope_key = :newScopeKey WHERE id = :id;") _setUpdateScopeKeyInternalnull82 abstract fun _setUpdateScopeKeyInternal(id: UUID, newScopeKey: String) 83 84 fun setUpdateCommitTime(update: UpdateEntity, commitTime: Date) { 85 update.commitTime = commitTime 86 _setUpdateCommitTime(update.id, commitTime) 87 } 88 89 @Query("UPDATE updates SET commit_time = :commitTime WHERE id = :id;") _setUpdateCommitTimenull90 abstract fun _setUpdateCommitTime(id: UUID, commitTime: Date) 91 92 @Transaction 93 open fun markUpdateFinished(update: UpdateEntity, hasSkippedEmbeddedAssets: Boolean) { 94 var statusToMark = UpdateStatus.READY 95 if (update.status === UpdateStatus.DEVELOPMENT) { 96 statusToMark = UpdateStatus.DEVELOPMENT 97 } else if (hasSkippedEmbeddedAssets) { 98 statusToMark = UpdateStatus.EMBEDDED 99 } 100 _markUpdateWithStatus(statusToMark, update.id) 101 _keepUpdate(update.id) 102 } 103 markUpdateFinishednull104 fun markUpdateFinished(update: UpdateEntity) { 105 markUpdateFinished(update, false) 106 } 107 markUpdateAccessednull108 fun markUpdateAccessed(update: UpdateEntity) { 109 val newLastAccessed = Date() 110 update.lastAccessed = newLastAccessed 111 _markUpdateAccessed(update.id, newLastAccessed) 112 } 113 114 @Query("UPDATE updates SET last_accessed = :lastAccessed WHERE id = :id;") _markUpdateAccessednull115 abstract fun _markUpdateAccessed(id: UUID, lastAccessed: Date) 116 117 fun incrementSuccessfulLaunchCount(update: UpdateEntity) { 118 update.successfulLaunchCount++ 119 _incrementSuccessfulLaunchCount(update.id) 120 } 121 122 @Query("UPDATE updates SET successful_launch_count = successful_launch_count + 1 WHERE id = :id;") _incrementSuccessfulLaunchCountnull123 abstract fun _incrementSuccessfulLaunchCount(id: UUID) 124 125 fun incrementFailedLaunchCount(update: UpdateEntity) { 126 update.failedLaunchCount++ 127 _incrementFailedLaunchCount(update.id) 128 } 129 130 @Query("UPDATE updates SET failed_launch_count = failed_launch_count + 1 WHERE id = :id;") _incrementFailedLaunchCountnull131 abstract fun _incrementFailedLaunchCount(id: UUID) 132 133 fun markUpdatesWithMissingAssets(missingAssets: List<AssetEntity>) { 134 val missingAssetIds = mutableListOf<Long>() 135 for (asset in missingAssets) { 136 missingAssetIds.add(asset.id) 137 } 138 _markUpdatesWithMissingAssets(missingAssetIds, UpdateStatus.PENDING) 139 } 140 141 @Delete deleteUpdatesnull142 abstract fun deleteUpdates(updates: List<UpdateEntity>) 143 } 144