2020-12-15 05:39:44 +13:00
< ? php
global $cli ;
2022-04-10 21:38:22 +12:00
global $register ;
2020-12-15 05:39:44 +13:00
2022-06-02 22:20:03 +12:00
use Appwrite\Auth\Auth ;
2022-05-12 05:04:31 +12:00
use Appwrite\Event\Certificate ;
2022-04-20 01:13:55 +12:00
use Appwrite\Event\Delete ;
2020-12-15 05:39:44 +13:00
use Utopia\App ;
2022-04-10 21:38:22 +12:00
use Utopia\Cache\Cache ;
2020-12-15 05:39:44 +13:00
use Utopia\CLI\Console ;
2022-04-10 21:38:22 +12:00
use Utopia\Database\Adapter\MariaDB ;
use Utopia\Database\Database ;
2022-07-13 01:32:39 +12:00
use Utopia\Database\DateTime ;
2022-04-10 21:38:22 +12:00
use Utopia\Cache\Adapter\Redis as RedisCache ;
2022-05-12 05:04:31 +12:00
use Utopia\Database\Document ;
2022-04-10 21:38:22 +12:00
use Utopia\Database\Query ;
2022-05-12 01:11:58 +12:00
function getConsoleDB () : Database
2022-04-10 21:38:22 +12:00
{
2022-05-12 01:11:58 +12:00
global $register ;
2022-04-10 21:38:22 +12:00
$attempts = 0 ;
do {
try {
$attempts ++ ;
2022-05-12 01:11:58 +12:00
$cache = new Cache ( new RedisCache ( $register -> get ( 'cache' )));
$database = new Database ( new MariaDB ( $register -> get ( 'db' )), $cache );
2022-04-10 21:38:22 +12:00
$database -> setDefaultDatabase ( App :: getEnv ( '_APP_DB_SCHEMA' , 'appwrite' ));
2022-05-12 01:11:58 +12:00
$database -> setNamespace ( '_console' ); // Main DB
2022-05-13 06:05:11 +12:00
2022-05-17 01:05:58 +12:00
if ( ! $database -> exists ( $database -> getDefaultDatabase (), 'certificates' )) {
2022-05-13 06:05:11 +12:00
throw new \Exception ( 'Console project not ready' );
}
2022-04-10 21:38:22 +12:00
break ; // leave loop if successful
2022-05-12 05:04:31 +12:00
} catch ( \Exception $e ) {
2022-04-10 21:38:22 +12:00
Console :: warning ( " Database not ready. Retrying connection ( { $attempts } )... " );
if ( $attempts >= DATABASE_RECONNECT_MAX_ATTEMPTS ) {
2022-05-12 05:04:31 +12:00
throw new \Exception ( 'Failed to connect to database: ' . $e -> getMessage ());
2022-04-10 21:38:22 +12:00
}
sleep ( DATABASE_RECONNECT_SLEEP );
}
} while ( $attempts < DATABASE_RECONNECT_MAX_ATTEMPTS );
2022-05-12 01:11:58 +12:00
return $database ;
}
2020-12-15 05:39:44 +13:00
$cli
-> task ( 'maintenance' )
-> desc ( 'Schedules maintenance tasks and publishes them to resque' )
-> action ( function () {
2021-01-27 09:49:13 +13:00
Console :: title ( 'Maintenance V1' );
2022-04-14 00:39:31 +12:00
Console :: success ( APP_NAME . ' maintenance process v1 has started' );
2021-01-27 09:49:13 +13:00
function notifyDeleteExecutionLogs ( int $interval )
{
2022-04-20 01:13:55 +12:00
( new Delete ())
-> setType ( DELETE_TYPE_EXECUTIONS )
2022-07-14 02:02:49 +12:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 1 * $interval ))
2022-04-20 01:13:55 +12:00
-> trigger ();
2021-01-27 09:49:13 +13:00
}
2022-04-14 00:39:31 +12:00
function notifyDeleteAbuseLogs ( int $interval )
2021-01-27 09:49:13 +13:00
{
2022-04-20 01:13:55 +12:00
( new Delete ())
-> setType ( DELETE_TYPE_ABUSE )
2022-07-14 02:02:49 +12:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 1 * $interval ))
2022-04-20 01:13:55 +12:00
-> trigger ();
2021-01-27 09:49:13 +13:00
}
2022-04-14 00:39:31 +12:00
function notifyDeleteAuditLogs ( int $interval )
2021-01-27 09:49:13 +13:00
{
2022-04-20 01:13:55 +12:00
( new Delete ())
-> setType ( DELETE_TYPE_AUDIT )
2022-07-14 02:02:49 +12:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 1 * $interval ))
2022-04-20 01:13:55 +12:00
-> trigger ();
2021-01-27 09:49:13 +13:00
}
2022-10-28 22:54:56 +13:00
function notifyDeleteUsageStats ( int $usageStatsRetentionHourly )
2021-08-27 23:37:52 +12:00
{
2022-04-20 01:13:55 +12:00
( new Delete ())
-> setType ( DELETE_TYPE_USAGE )
2022-10-28 22:54:56 +13:00
-> setUsageRetentionHourlyDateTime ( DateTime :: addSeconds ( new \DateTime (), - 1 * $usageStatsRetentionHourly ))
2022-04-20 01:13:55 +12:00
-> trigger ();
2021-08-27 23:37:52 +12:00
}
2022-04-14 00:39:31 +12:00
function notifyDeleteConnections ()
2021-06-16 21:35:37 +12:00
{
2022-04-20 01:13:55 +12:00
( new Delete ())
-> setType ( DELETE_TYPE_REALTIME )
2022-07-14 02:02:49 +12:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 60 ))
2022-04-20 01:13:55 +12:00
-> trigger ();
2021-06-16 21:35:37 +12:00
}
2022-06-02 22:20:03 +12:00
function notifyDeleteExpiredSessions ()
{
( new Delete ())
-> setType ( DELETE_TYPE_SESSIONS )
2022-11-01 03:54:15 +13:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 1 * Auth :: TOKEN_EXPIRATION_LOGIN_LONG )) //TODO: Update to use project session expiration instead of default.
2022-06-02 22:20:03 +12:00
-> trigger ();
}
2022-04-10 21:38:22 +12:00
function renewCertificates ( $dbForConsole )
{
2022-07-14 02:02:49 +12:00
$time = DateTime :: now ();
2022-07-12 03:12:41 +12:00
2022-04-10 21:38:22 +12:00
$certificates = $dbForConsole -> find ( 'certificates' , [
2022-09-07 23:57:08 +12:00
Query :: lessThan ( 'attempts' , 5 ), // Maximum 5 attempts
2022-09-03 02:19:36 +12:00
Query :: lessThanEqual ( 'renewDate' , $time ), // includes 60 days cooldown (we have 30 days to renew)
Query :: limit ( 200 ), // Limit 200 comes from LetsEncrypt (300 orders per 3 hours, keeping some for new domains)
]);
2022-04-10 21:38:22 +12:00
2022-05-12 05:04:31 +12:00
if ( \count ( $certificates ) > 0 ) {
2022-04-10 21:38:22 +12:00
Console :: info ( " [ { $time } ] Found " . \count ( $certificates ) . " certificates for renewal, scheduling jobs. " );
2022-05-12 05:04:31 +12:00
$event = new Certificate ();
2022-04-10 21:38:22 +12:00
foreach ( $certificates as $certificate ) {
2022-05-12 05:04:31 +12:00
$event
-> setDomain ( new Document ([
'domain' => $certificate -> getAttribute ( 'domain' )
]))
-> trigger ();
2022-04-10 21:38:22 +12:00
}
} else {
Console :: info ( " [ { $time } ] No certificates for renewal. " );
}
}
2022-07-03 21:36:59 +12:00
function notifyDeleteCache ( $interval )
{
( new Delete ())
2022-08-15 21:05:41 +12:00
-> setType ( DELETE_TYPE_CACHE_BY_TIMESTAMP )
2022-08-23 17:23:01 +12:00
-> setDatetime ( DateTime :: addSeconds ( new \DateTime (), - 1 * $interval ))
2022-07-03 21:36:59 +12:00
-> trigger ();
}
2020-12-18 23:48:00 +13:00
// # of days in seconds (1 day = 86400s)
2021-01-21 06:57:49 +13:00
$interval = ( int ) App :: getEnv ( '_APP_MAINTENANCE_INTERVAL' , '86400' );
2021-01-21 07:23:48 +13:00
$executionLogsRetention = ( int ) App :: getEnv ( '_APP_MAINTENANCE_RETENTION_EXECUTION' , '1209600' );
$auditLogRetention = ( int ) App :: getEnv ( '_APP_MAINTENANCE_RETENTION_AUDIT' , '1209600' );
$abuseLogsRetention = ( int ) App :: getEnv ( '_APP_MAINTENANCE_RETENTION_ABUSE' , '86400' );
2022-10-28 22:54:56 +13:00
$usageStatsRetentionHourly = ( int ) App :: getEnv ( '_APP_MAINTENANCE_RETENTION_USAGE_HOURLY' , '8640000' ); //100 days
2022-10-23 20:29:13 +13:00
2022-07-03 21:36:59 +12:00
$cacheRetention = ( int ) App :: getEnv ( '_APP_MAINTENANCE_RETENTION_CACHE' , '2592000' ); // 30 days
2020-12-15 10:26:37 +13:00
2022-10-28 22:54:56 +13:00
Console :: loop ( function () use ( $interval , $executionLogsRetention , $abuseLogsRetention , $auditLogRetention , $usageStatsRetentionHourly , $cacheRetention ) {
2022-05-12 01:11:58 +12:00
$database = getConsoleDB ();
2022-07-14 02:02:49 +12:00
$time = DateTime :: now ();
2022-07-12 03:12:41 +12:00
2022-05-12 01:11:58 +12:00
Console :: info ( " [ { $time } ] Notifying workers with maintenance tasks every { $interval } seconds " );
2021-01-21 04:28:52 +13:00
notifyDeleteExecutionLogs ( $executionLogsRetention );
2021-01-21 06:57:49 +13:00
notifyDeleteAbuseLogs ( $abuseLogsRetention );
notifyDeleteAuditLogs ( $auditLogRetention );
2022-10-28 22:54:56 +13:00
notifyDeleteUsageStats ( $usageStatsRetentionHourly );
2021-06-18 22:00:27 +12:00
notifyDeleteConnections ();
2022-06-02 22:20:03 +12:00
notifyDeleteExpiredSessions ();
2022-05-12 01:11:58 +12:00
renewCertificates ( $database );
2022-07-03 21:36:59 +12:00
notifyDeleteCache ( $cacheRetention );
2021-01-21 06:57:49 +13:00
}, $interval );
2022-04-14 00:39:31 +12:00
});