Auto update checks are now asynchronous, improves startup time (#433)

This commit is contained in:
Dylan K. Taylor 2017-03-17 14:43:12 +00:00 committed by GitHub
parent bcbb5de5bb
commit fa5e66478c
2 changed files with 146 additions and 38 deletions

View File

@ -31,63 +31,60 @@ class AutoUpdater{
/** @var Server */
protected $server;
/** @var string */
protected $endpoint;
/** @var bool */
protected $hasUpdate = false;
/** @var array|null */
protected $updateInfo = null;
/**
* @param Server $server
* @param string $endpoint
*/
public function __construct(Server $server, $endpoint){
$this->server = $server;
$this->endpoint = "http://$endpoint/api/";
if($server->getProperty("auto-updater.enabled", true)){
$this->check();
if($this->hasUpdate()){
if($this->server->getProperty("auto-updater.on-update.warn-console", true)){
$this->showConsoleUpdate();
}
}elseif($this->server->getProperty("auto-updater.preferred-channel", true)){
$version = new VersionString();
if(!$version->isDev() and $this->getChannel() !== "stable"){
$this->showChannelSuggestionStable();
}elseif($version->isDev() and $this->getChannel() === "stable"){
$this->showChannelSuggestionBeta();
}
$this->doCheck();
}
}
/**
* Callback used at the end of the update checking task
*
* @param array $updateInfo
*/
public function checkUpdateCallback(array $updateInfo){
$this->updateInfo = $updateInfo;
$this->checkUpdate();
if($this->hasUpdate()){
if($this->server->getProperty("auto-updater.on-update.warn-console", true)){
$this->showConsoleUpdate();
}
}elseif($this->server->getProperty("auto-updater.preferred-channel", true)){
$version = new VersionString();
if(!$version->isDev() and $this->getChannel() !== "stable"){
$this->showChannelSuggestionStable();
}elseif($version->isDev() and $this->getChannel() === "stable"){
$this->showChannelSuggestionBeta();
}
}
}
protected function check(){
$error = "";
$response = Utils::getURL($this->endpoint . "?channel=" . $this->getChannel(), 4, [], $error);
if($error !== ""){
$this->server->getLogger()->debug("[AutoUpdater] Update check failed due to \"$error\"");
return;
}
$response = json_decode($response, true);
if(!is_array($response)){
return;
}
$this->updateInfo = [
"version" => $response["version"],
"api_version" => $response["api_version"],
"build" => $response["build"],
"date" => $response["date"],
"details_url" => $response["details_url"] ?? null,
"download_url" => $response["download_url"]
];
$this->checkUpdate();
}
/**
* Returns whether there is an update available.
*
* @return bool
*/
public function hasUpdate(){
return $this->hasUpdate;
}
/**
* Posts a warning to the console to tell the user there is an update available
*/
public function showConsoleUpdate(){
$logger = $this->server->getLogger();
$newVersion = new VersionString($this->updateInfo["version"]);
@ -100,6 +97,10 @@ class AutoUpdater{
$logger->warning("----- -------------------------- -----");
}
/**
* Shows a warning to a player to tell them there is an update available
* @param Player $player
*/
public function showPlayerUpdate(Player $player){
$player->sendMessage(TextFormat::DARK_PURPLE . "The version of PocketMine-MP that this server is running is out of date. Please consider updating to the latest version.");
$player->sendMessage(TextFormat::DARK_PURPLE . "Check the console for more details.");
@ -121,14 +122,25 @@ class AutoUpdater{
$logger->info("----- -------------------------- -----");
}
/**
* Returns the last retrieved update data.
*
* @return array|null
*/
public function getUpdateInfo(){
return $this->updateInfo;
}
/**
* Schedules an AsyncTask to check for an update.
*/
public function doCheck(){
$this->check();
$this->server->getScheduler()->scheduleAsyncTask(new UpdateCheckTask($this->endpoint, $this->getChannel()));
}
/**
* Checks the update information against the current server version to decide if there's an update
*/
protected function checkUpdate(){
if($this->updateInfo === null){
return;
@ -144,6 +156,11 @@ class AutoUpdater{
}
/**
* Returns the channel used for update checking (stable, beta, dev)
*
* @return string
*/
public function getChannel(){
$channel = strtolower($this->server->getProperty("auto-updater.preferred-channel", "stable"));
if($channel !== "stable" and $channel !== "beta" and $channel !== "development"){
@ -152,4 +169,13 @@ class AutoUpdater{
return $channel;
}
/**
* Returns the host used for update checks.
*
* @return string
*/
public function getEndpoint() : string{
return $this->endpoint;
}
}

View File

@ -0,0 +1,82 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
namespace pocketmine\updater;
use pocketmine\scheduler\AsyncTask;
use pocketmine\Server;
use pocketmine\utils\Utils;
class UpdateCheckTask extends AsyncTask{
/** @var string */
private $endpoint;
/** @var string */
private $channel;
/** @var string */
private $error;
public function __construct(string $endpoint, string $channel){
$this->endpoint = $endpoint;
$this->channel = $channel;
}
public function onRun(){
$this->error = "";
$response = Utils::getURL($this->endpoint . "?channel=" . $this->channel, 4, [], $this->error);
if($this->error !== ""){
return;
}else{
$response = json_decode($response, true);
if(is_array($response)){
$this->setResult(
[
"version" => $response["version"],
"api_version" => $response["api_version"],
"build" => $response["build"],
"date" => $response["date"],
"details_url" => $response["details_url"] ?? null,
"download_url" => $response["download_url"]
],
true
);
}else{
$this->error = "Invalid response data";
}
}
}
public function onCompletion(Server $server){
if($this->error !== ""){
$server->getLogger()->debug("[AutoUpdater] Async update check failed due to \"$this->error\"");
}else{
$updateInfo = $this->getResult();
if(is_array($updateInfo)){
$server->getUpdater()->checkUpdateCallback($updateInfo);
}else{
$server->getLogger()->debug("[AutoUpdater] Update info error");
}
}
}
}