mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-04 11:39:39 +00:00 
			
		
		
		
	Persistent store fixes and /pstore command
- Fixes find() and getAll() to run in a transaction. - Add /pstore command which has debug utilities.
This commit is contained in:
		@ -60,7 +60,7 @@ class FoundationCorePlugin : JavaPlugin(), Listener {
 | 
			
		||||
    registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
 | 
			
		||||
    registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
 | 
			
		||||
    registerCommandExecutor(listOf("leaderboard", "lb"), LeaderboardCommand())
 | 
			
		||||
    registerCommandExecutor(listOf("pstorestats"), StoreStatsCommand(this))
 | 
			
		||||
    registerCommandExecutor(listOf("pstore"), PersistentStoreCommand(this))
 | 
			
		||||
 | 
			
		||||
    val log = slF4JLogger
 | 
			
		||||
    log.info("Features:")
 | 
			
		||||
@ -128,4 +128,4 @@ class FoundationCorePlugin : JavaPlugin(), Listener {
 | 
			
		||||
 | 
			
		||||
    const val BACKUP_ENABLED = true
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
package cloud.kubelet.foundation.core.command
 | 
			
		||||
 | 
			
		||||
import cloud.kubelet.foundation.core.FoundationCorePlugin
 | 
			
		||||
import jetbrains.exodus.entitystore.Entity
 | 
			
		||||
import org.bukkit.command.Command
 | 
			
		||||
import org.bukkit.command.CommandExecutor
 | 
			
		||||
import org.bukkit.command.CommandSender
 | 
			
		||||
import java.util.*
 | 
			
		||||
 | 
			
		||||
class PersistentStoreCommand(private val plugin: FoundationCorePlugin) : CommandExecutor {
 | 
			
		||||
  override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
 | 
			
		||||
    if (args.isEmpty()) {
 | 
			
		||||
      sender.sendMessage("Invalid Command Usage.")
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    when (args[0]) {
 | 
			
		||||
      "stats" -> {
 | 
			
		||||
        plugin.persistentStores.forEach { (name, store) ->
 | 
			
		||||
          val counts = store.transact {
 | 
			
		||||
            entityTypes.associateWith { type -> getAll(type).size() }.toSortedMap()
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          sender.sendMessage(
 | 
			
		||||
            "Store $name ->",
 | 
			
		||||
            *counts.map { "  ${it.key} -> ${it.value} entries" }.toTypedArray()
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      "sample" -> {
 | 
			
		||||
        if (args.size != 3) {
 | 
			
		||||
          sender.sendMessage("Invalid Subcommand Usage.")
 | 
			
		||||
          return true
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val storeName = args[1]
 | 
			
		||||
        val entityTypeName = args[2]
 | 
			
		||||
        val store = plugin.getPersistentStore(storeName)
 | 
			
		||||
        val random = Random()
 | 
			
		||||
        store.transact {
 | 
			
		||||
          val entities = getAll(entityTypeName)
 | 
			
		||||
          val results = mutableListOf<Entity>()
 | 
			
		||||
          for (entity in entities) {
 | 
			
		||||
            if (random.nextBoolean()) {
 | 
			
		||||
              results.add(entity)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (results.size == 3) {
 | 
			
		||||
              break
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          for (result in results) {
 | 
			
		||||
            sender.sendMessage(
 | 
			
		||||
              "Entity ${result.id.localId} ->",
 | 
			
		||||
              *result.propertyNames.map { "  ${it}: ${result.getProperty(it)}" }.toTypedArray()
 | 
			
		||||
            )
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      else -> {
 | 
			
		||||
        sender.sendMessage("Unknown Subcommand.")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return true
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -1,22 +0,0 @@
 | 
			
		||||
package cloud.kubelet.foundation.core.command
 | 
			
		||||
 | 
			
		||||
import cloud.kubelet.foundation.core.FoundationCorePlugin
 | 
			
		||||
import org.bukkit.command.Command
 | 
			
		||||
import org.bukkit.command.CommandExecutor
 | 
			
		||||
import org.bukkit.command.CommandSender
 | 
			
		||||
 | 
			
		||||
class StoreStatsCommand(private val plugin: FoundationCorePlugin) : CommandExecutor {
 | 
			
		||||
  override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
 | 
			
		||||
    plugin.persistentStores.forEach { (name, store) ->
 | 
			
		||||
      val counts = store.transact { tx ->
 | 
			
		||||
        tx.entityTypes.associateWith { type -> tx.getAll(type).size() }.toSortedMap()
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      sender.sendMessage(
 | 
			
		||||
        "Store $name ->",
 | 
			
		||||
        *counts.map { "  ${it.key} -> ${it.value} entries" }.toTypedArray()
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    return true
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -10,7 +10,7 @@ class PersistentStore(corePlugin: FoundationCorePlugin, fileStoreName: String) :
 | 
			
		||||
  private val fileStorePath = corePlugin.pluginDataPath.resolve("persistence/${fileStoreName}")
 | 
			
		||||
  private val entityStore = PersistentEntityStores.newInstance(fileStorePath.toFile())
 | 
			
		||||
 | 
			
		||||
  fun <R> transact(block: (StoreTransaction) -> R): R {
 | 
			
		||||
  fun <R> transact(block: StoreTransaction.() -> R): R {
 | 
			
		||||
    var result: R? = null
 | 
			
		||||
    entityStore.executeInTransaction { tx ->
 | 
			
		||||
      result = block(tx)
 | 
			
		||||
@ -18,16 +18,15 @@ class PersistentStore(corePlugin: FoundationCorePlugin, fileStoreName: String) :
 | 
			
		||||
    return result!!
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fun create(entityTypeName: String, populate: Entity.() -> Unit) = transact { tx ->
 | 
			
		||||
    val entity = tx.newEntity(entityTypeName)
 | 
			
		||||
    populate(entity)
 | 
			
		||||
  fun create(entityTypeName: String, populate: Entity.() -> Unit) = transact {
 | 
			
		||||
    populate(newEntity(entityTypeName))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fun getAll(entityTypeName: String) =
 | 
			
		||||
    transact { tx -> tx.getAll(entityTypeName) }
 | 
			
		||||
  fun <R> getAll(entityTypeName: String, block: (EntityIterable) -> R): R =
 | 
			
		||||
    transact { block(getAll(entityTypeName)) }
 | 
			
		||||
 | 
			
		||||
  fun <T> find(entityTypeName: String, propertyName: String, value: Comparable<T>): EntityIterable =
 | 
			
		||||
    transact { tx -> tx.find(entityTypeName, propertyName, value) }
 | 
			
		||||
  fun <T, R> find(entityTypeName: String, propertyName: String, value: Comparable<T>, block: (EntityIterable) -> R): R =
 | 
			
		||||
    transact { block(find(entityTypeName, propertyName, value)) }
 | 
			
		||||
 | 
			
		||||
  override fun close() {
 | 
			
		||||
    entityStore.close()
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,7 @@ commands:
 | 
			
		||||
    aliases:
 | 
			
		||||
      - lb
 | 
			
		||||
    permission: foundation.command.leaderboard
 | 
			
		||||
  pstorestats:
 | 
			
		||||
    description: Persistent Store Stats
 | 
			
		||||
    usage: /pstorestats
 | 
			
		||||
    permission: foundation.command.pstorestats
 | 
			
		||||
  pstore:
 | 
			
		||||
    description: Persistent Store Manager
 | 
			
		||||
    usage: /pstore
 | 
			
		||||
    permission: foundation.command.pstore
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user