mirror of
				https://github.com/packwiz/packwiz-installer.git
				synced 2025-10-30 18:44:32 +01:00 
			
		
		
		
	WIP task system with lazy evaluation
This commit is contained in:
		| @@ -35,6 +35,7 @@ dependencies { | ||||
| 	implementation("com.squareup.okio:okio:3.0.0") | ||||
| 	implementation(kotlin("stdlib-jdk8")) | ||||
| 	implementation("com.squareup.okhttp3:okhttp:4.9.3") | ||||
| 	implementation("com.michael-bull.kotlin-result:kotlin-result:1.1.14") | ||||
| } | ||||
|  | ||||
| application { | ||||
|   | ||||
| @@ -88,6 +88,8 @@ class PackwizPath(path: String, base: Base) { | ||||
| 		 * @throws RequestException | ||||
| 		 */ | ||||
| 		fun source(path: String, clientHolder: ClientHolder): BufferedSource | ||||
|  | ||||
| 		operator fun div(path: String) = PackwizPath(path, this) | ||||
| 	} | ||||
|  | ||||
| 	interface SinkableBase: Base { | ||||
|   | ||||
| @@ -0,0 +1,3 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| data class CacheKey<T>(val key: String, val version: Int) | ||||
| @@ -0,0 +1,22 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| import kotlin.reflect.KProperty | ||||
|  | ||||
| class CacheManager { | ||||
| 	class CacheValue<T> { | ||||
| 		operator fun getValue(thisVal: Any?, property: KProperty<*>): T { | ||||
| 			TODO("Not yet implemented") | ||||
| 		} | ||||
|  | ||||
| 		operator fun setValue(thisVal: Any?, property: KProperty<*>, value: T) { | ||||
| 			TODO("Not yet implemented") | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	operator fun <T> get(cacheKey: CacheKey<T>): CacheValue<T> { | ||||
| 		return CacheValue() | ||||
| 	} | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										20
									
								
								src/main/kotlin/link/infra/packwiz/installer/task/Task.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/main/kotlin/link/infra/packwiz/installer/task/Task.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| import kotlin.reflect.KMutableProperty0 | ||||
|  | ||||
| // TODO: task processing on 1 background thread; actual resolving of values calls out to a thread group | ||||
| // TODO: progress bar is updated from each of these tasks | ||||
| // TODO: have everything be lazy so there's no need to determine task ordering upfront? a bit like rust async - task results must be queried to occur | ||||
|  | ||||
| abstract class Task<T>(protected val ctx: TaskContext): TaskInput<T> { | ||||
| 	// TODO: lazy wrapper for fallible results | ||||
| 	// TODO: multithreaded fanout subclass/helper | ||||
|  | ||||
| 	protected fun <T> wasUpdated(value: KMutableProperty0<T>, newValue: T): Boolean { | ||||
| 		if (value.get() == newValue) { | ||||
| 			return false | ||||
| 		} | ||||
| 		value.set(newValue) | ||||
| 		return true | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| /** | ||||
|  * An object for storing results where result and upToDate are calculated simultaneously | ||||
|  */ | ||||
| data class TaskCombinedResult<T>(val result: T, val upToDate: Boolean) | ||||
| @@ -0,0 +1,12 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| import link.infra.packwiz.installer.target.ClientHolder | ||||
|  | ||||
| class TaskContext { | ||||
| 	// TODO: thread pools, protocol roots | ||||
| 	// TODO: cache management | ||||
|  | ||||
| 	val cache = CacheManager() | ||||
|  | ||||
| 	val clients = ClientHolder() | ||||
| } | ||||
| @@ -0,0 +1,29 @@ | ||||
| package link.infra.packwiz.installer.task | ||||
|  | ||||
| import kotlin.reflect.KProperty | ||||
|  | ||||
| interface TaskInput<T> { | ||||
| 	/** | ||||
| 	 * The value of this task input. May be lazily evaluated; must be threadsafe. | ||||
| 	 */ | ||||
| 	val value: T | ||||
|  | ||||
| 	/** | ||||
| 	 * True if the effective value of this input has changed since the task was last run. | ||||
| 	 * Doesn't require evaluation of the input value; should use cached data if possible. | ||||
| 	 * May be lazily evaluated; must be threadsafe. | ||||
| 	 */ | ||||
| 	val upToDate: Boolean | ||||
|  | ||||
| 	operator fun getValue(thisVal: Any?, property: KProperty<*>): T = value | ||||
|  | ||||
| 	companion object { | ||||
| 		fun <T> raw(value: T): TaskInput<T> { | ||||
| 			return object: TaskInput<T> { | ||||
| 				override val value = value | ||||
| 				override val upToDate: Boolean | ||||
| 					get() = false | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,6 @@ | ||||
| package link.infra.packwiz.installer.task.formats.packwizv1 | ||||
|  | ||||
| import link.infra.packwiz.installer.metadata.hash.Hash | ||||
| import link.infra.packwiz.installer.target.path.PackwizPath | ||||
|  | ||||
| data class PackwizV1PackFile(val name: String, val indexPath: PackwizPath, val indexHash: Hash) | ||||
| @@ -0,0 +1,47 @@ | ||||
| package link.infra.packwiz.installer.task.formats.packwizv1 | ||||
|  | ||||
| import com.google.gson.annotations.SerializedName | ||||
| import com.moandjiezana.toml.Toml | ||||
| import link.infra.packwiz.installer.metadata.hash.Hash | ||||
| import link.infra.packwiz.installer.metadata.hash.HashUtils | ||||
| import link.infra.packwiz.installer.target.path.PackwizPath | ||||
| import link.infra.packwiz.installer.task.CacheKey | ||||
| import link.infra.packwiz.installer.task.Task | ||||
| import link.infra.packwiz.installer.task.TaskCombinedResult | ||||
| import link.infra.packwiz.installer.task.TaskContext | ||||
|  | ||||
| class PackwizV1PackTomlTask(ctx: TaskContext, val path: PackwizPath): Task<PackwizV1PackFile>(ctx) { | ||||
| 	// TODO: make hierarchically defined by caller? - then changing the pack format type doesn't leave junk in the cache | ||||
| 	private var cache by ctx.cache[CacheKey<Hash>("packwiz.v1.packtoml.hash", 1)] | ||||
|  | ||||
| 	private class PackFile { | ||||
| 		var name: String? = null | ||||
| 		var index: IndexFileLoc? = null | ||||
|  | ||||
| 		class IndexFileLoc { | ||||
| 			var file: String? = null | ||||
| 			@SerializedName("hash-format") | ||||
| 			var hashFormat: String? = null | ||||
| 			var hash: String? = null | ||||
| 		} | ||||
|  | ||||
| 		var versions: Map<String, String>? = null | ||||
| 	} | ||||
|  | ||||
| 	private val internalResult by lazy { | ||||
| 		// TODO: query, parse JSON | ||||
| 		val packFile = Toml().read(path.source(ctx.clients).inputStream()).to(PackFile::class.java) | ||||
|  | ||||
| 		val resolved = PackwizV1PackFile(packFile.name ?: throw RuntimeException("Name required"), // TODO: better exception handling | ||||
| 			path.resolve(packFile.index?.file ?: throw RuntimeException("File required")), | ||||
| 			HashUtils.getHash(packFile.index?.hashFormat ?: throw RuntimeException("Hash format required"), | ||||
| 				packFile.index?.hash ?: throw RuntimeException("Hash required")) | ||||
| 		) | ||||
| 		val hash = HashUtils.getHash("sha256", "whatever was just read") | ||||
|  | ||||
| 		TaskCombinedResult(resolved, wasUpdated(::cache, hash)) | ||||
| 	} | ||||
|  | ||||
| 	override val value by internalResult::result | ||||
| 	override val upToDate by internalResult::upToDate | ||||
| } | ||||
| @@ -9,6 +9,7 @@ packwiz-installer itself is under the MIT license ([Source](https://github.com/p | ||||
| - Jetbrains Annotations 13.0: Apache 2.0 ([Source](https://github.com/JetBrains/java-annotations)) | ||||
| - Kotlin Standard Library 1.6.10: Apache 2.0 ([Source](https://github.com/JetBrains/kotlin)) | ||||
| - toml4j 0.7.2: MIT ([Source](https://github.com/mwanji/toml4j)) | ||||
| <!-- TODO: document kotlin-result --> | ||||
|  | ||||
| ## Associated notices | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user