Schedule system

Сообщения
6
Реакции
0
Всем привет.
В @nestjs есть модуль @nestjs/schedule.

Кто-нибудь делал подобное в amxx
Например
@Cron('0 0 0 1 */3 *')

Мне пока в голову только приходит из nodejs по расписанию Cron отправлять пакет,
а amxx делает socket_recv и уже обрабатывает команду по расписанию.

И передавать допустим из nodejs следующий json { event: string, params: [] string | number | object, time: string }

Но больше хотелось бы в самом amxx выполнять команду чем вызывать ее из другого приложения
 
В чём конкретно заключается задача?

хорошо бы иметь какой-то подобный модуль или плагин
Сгенерировано ChatGPT (не имплементировано):
// vim: set ts=4 sw=4 tw=99 noet:
//
// HLDS Cron
// Copyright (C) hlds.run contributors.
//
// Cron scheduler API for AMX Mod X plugins.
//
// This include provides the public API for a cron scheduler. Include it in
// any plugin that needs wall-clock scheduling:
//
//     #include <cron>
//
// The scheduler uses the familiar five-field cron notation:
//
//     ┌──────── minute       0-59
//     │ ┌────── hour         0-23
//     │ │ ┌──── day of month 1-31
//     │ │ │ ┌── month        1-12
//     │ │ │ │ ┌ day of week 0-6 (Sunday = 0)
//     │ │ │ │ │
//     * * * * *
//
// Supported expressions:
//     *       any value
//     */n     every n units
//     a       exact value
//     a-b     inclusive range
//     a,b,c   list
//     a-b/n   range with step
//
// Examples:
//     */5 * * * *     Every five minutes
//     0 * * * *       Every hour
//     0 4 * * *       Every day at 04:00
//     30 3 * * 1-5    Weekdays at 03:30
//     0 0 1 * *       First day of every month
//
// Cron jobs use server local wall-clock time. Cron is intended for calendar
// schedules; use cron_every() for elapsed-time intervals.
//
// The API is deliberately small and follows the style of AMX Mod X include
// files: constants first, then public declarations, then detailed native
// documentation and examples.
//
// See the AMX Mod X module/include documentation for the native model and
// include conventions.

#if defined _cron_included
    #endinput
#endif
#define _cron_included

/**
 * No special scheduler flags.
 */
#define CRON_FLAG_NONE            0

/**
 * Run the job once immediately after registration, then continue normally.
 */
#define CRON_FLAG_RUN_ON_START    (1 << 0)

/**
 * Do not execute occurrences that were missed while the scheduler was not
 * running. This is the recommended default.
 */
#define CRON_FLAG_SKIP_MISSED     (1 << 1)

/**
 * Replay missed occurrences after the scheduler resumes.
 *
 * Implementations should protect against an excessive number of executions
 * with an internal replay limit.
 */
#define CRON_FLAG_REPLAY_MISSED   (1 << 2)

/**
 * Execute at the next matching cron occurrence and remove the job.
 */
#define CRON_FLAG_ONCE             (1 << 3)

/**
 * Result returned by cron_validate() and lifecycle functions.
 */
enum CronResult
{
    CRON_OK = 0,
    CRON_ERR_INVALID_EXPRESSION,
    CRON_ERR_INVALID_CALLBACK,
    CRON_ERR_INVALID_FLAGS,
    CRON_ERR_LIMIT_REACHED,
    CRON_ERR_NOT_FOUND,
    CRON_ERR_ALREADY_EXISTS,
    CRON_ERR_INTERNAL
};

/**
 * Current scheduler state.
 */
enum CronSchedulerState
{
    CRON_STATE_STOPPED = 0,
    CRON_STATE_RUNNING
};

/**
 * Creates a recurring cron job.
 *
 * The callback must be a public Pawn function with the following signature:
 *
 *     public my_callback(job_id)
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param callback
 *     Name of the public callback function.
 *
 * @param flags
 *     Combination of CRON_FLAG_* values.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @note The callback is executed in the normal AMX Mod X execution context.
 *       It must not perform long-running blocking work.
 *
 * @example
 *     public plugin_init()
 *     {
 *         cron_schedule("*/5 * * * *", "cron_five_minutes");
 *     }
 *
 *     public cron_five_minutes(job_id)
 *     {
 *         server_print("[CRON] job #%d", job_id);
 *     }
 */
native cron_schedule(const expression[], const callback[], flags = CRON_FLAG_SKIP_MISSED);

/**
 * Creates a recurring cron job with a stable human-readable name.
 *
 * Named jobs are useful for administration, diagnostics and idempotent
 * registration.
 *
 * @param name
 *     Unique job name, for example "daily_cleanup".
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param callback
 *     Name of the public callback function.
 *
 * @param flags
 *     Combination of CRON_FLAG_* values.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @note Job names are unique within the scheduler.
 *
 * @example
 *     public plugin_init()
 *     {
 *         cron_schedule_named(
 *             "daily_cleanup",
 *             "0 3 * * *",
 *             "cron_daily_cleanup"
 *         );
 *     }
 */
native cron_schedule_named(
    const name[],
    const expression[],
    const callback[],
    flags = CRON_FLAG_SKIP_MISSED
);

/**
 * Cancels a job.
 *
 * @param job_id
 *     Job ID returned by cron_schedule() or cron_schedule_named().
 *
 * @return
 *     true if the job existed and was cancelled.
 */
native bool:cron_cancel(job_id);

/**
 * Cancels a named job.
 *
 * @param name
 *     Name supplied to cron_schedule_named().
 *
 * @return
 *     true if the job existed and was cancelled.
 */
native bool:cron_cancel_named(const name[]);

/**
 * Checks whether a job exists.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     true if the job is active.
 */
native bool:cron_exists(job_id);

/**
 * Checks whether a named job exists.
 *
 * @param name
 *     Job name.
 *
 * @return
 *     true if the job is active.
 */
native bool:cron_exists_named(const name[]);

/**
 * Cancels all jobs owned by the calling plugin.
 *
 * @note The scheduler automatically removes jobs when their owning plugin
 *       is unloaded.
 */
native cron_cancel_all();

/**
 * Returns the number of active jobs owned by the calling plugin.
 *
 * @return
 *     Number of active jobs.
 */
native cron_count();

/**
 * Returns the total number of active jobs in the scheduler.
 *
 * @return
 *     Number of active jobs.
 */
native cron_total();

/**
 * Starts the scheduler.
 *
 * Normally the scheduler starts automatically. This function exists for
 * explicit lifecycle control and testing.
 *
 * @return
 *     CRON_OK on success.
 */
native CronResult:cron_start();

/**
 * Stops the scheduler without removing registered jobs.
 *
 * Starting it again resumes scheduling.
 *
 * @return
 *     CRON_OK on success.
 */
native CronResult:cron_stop();

/**
 * Returns the current scheduler state.
 *
 * @return
 *     CRON_STATE_STOPPED or CRON_STATE_RUNNING.
 */
native CronSchedulerState:cron_state();

/**
 * Validates a cron expression.
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param error
 *     Buffer receiving a human-readable error message.
 *
 * @param error_len
 *     Size of the error buffer.
 *
 * @return
 *     CRON_OK when valid, otherwise an appropriate CRON_ERR_* value.
 *
 * @example
 *     new error[128];
 *
 *     if (cron_validate("0 25 * * *", error, charsmax(error)) != CRON_OK)
 *     {
 *         server_print("[CRON] %s", error);
 *     }
 */
native CronResult:cron_validate(const expression[], error[], error_len);

/**
 * Calculates the next matching timestamp for an expression.
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param from_timestamp
 *     Unix timestamp from which the search starts. If 0, current server time
 *     is used.
 *
 * @return
 *     Unix timestamp of the next occurrence, or 0 when no occurrence exists.
 *
 * @example
 *     new timestamp = cron_next("0 4 * * *");
 *
 *     if (timestamp)
 *     {
 *         new date[32];
 *         format_time(date, charsmax(date), "%Y-%m-%d %H:%M:%S", timestamp);
 *         server_print("[CRON] next run: %s", date);
 *     }
 */
native cron_next(const expression[], from_timestamp = 0);

/**
 * Returns the timestamp of the last execution of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     Unix timestamp, or 0 if the job has never executed or does not exist.
 */
native cron_last_run(job_id);

/**
 * Returns the timestamp of the next execution of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     Unix timestamp, or 0 if the job does not exist.
 */
native cron_next_run(job_id);

/**
 * Gets the name of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_name(job_id, buffer[], buffer_len);

/**
 * Gets the cron expression of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_expression(job_id, buffer[], buffer_len);

/**
 * Gets the callback name of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_callback(job_id, buffer[], buffer_len);

/**
 * Immediately dispatches a job.
 *
 * Manual execution does not modify the cron schedule or next occurrence.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     true when the job was found and dispatched.
 *
 * @note This is intended for administration, testing and diagnostics.
 */
native bool:cron_trigger(job_id);

/**
 * Creates a one-shot elapsed-time job.
 *
 * @param delay
 *     Delay in seconds.
 *
 * @param callback
 *     Public callback name.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @example
 *     cron_once(30.0, "cron_after_thirty_seconds");
 *
 *     public cron_after_thirty_seconds(job_id)
 *     {
 *         server_print("[CRON] delayed task");
 *     }
 */
native cron_once(Float:delay, const callback[]);

/**
 * Creates a recurring elapsed-time job.
 *
 * Unlike cron_schedule(), this function is based on elapsed time rather than
 * calendar time.
 *
 * @param interval
 *     Interval in seconds.
 *
 * @param callback
 *     Public callback name.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @example
 *     cron_every(60.0, "cron_every_minute");
 *
 *     public cron_every_minute(job_id)
 *     {
 *         server_print("[CRON] interval task");
 *     }
 */
native cron_every(Float:interval, const callback[]);

/**
 * Sets the scheduler log level.
 *
 * Suggested levels:
 *
 *     0 - errors only
 *     1 - normal
 *     2 - verbose/debug
 *
 * @param level
 *     Desired log level.
 */
native cron_set_log_level(level);

/* -------------------------------------------------------------------------- */
/* Callback contract                                                          */
/* -------------------------------------------------------------------------- */

/**
 * Cron callbacks receive exactly one argument: the job ID.
 *
 * Example:
 *
 *     public cron_daily_cleanup(job_id)
 *     {
 *         // Do a short, non-blocking operation.
 *     }
 *
 * The scheduler invokes callbacks synchronously. A callback should therefore
 * return quickly and should never wait for external I/O.
 */

/* -------------------------------------------------------------------------- */
/* Cron expression reference                                                  */
/* -------------------------------------------------------------------------- */

/**
 * Minute
 *
 *     0-59
 *
 * Hour
 *
 *     0-23
 *
 * Day of month
 *
 *     1-31
 *
 * Month
 *
 *     1-12
 *
 * Day of week
 *
 *     0-6
 *     Sunday = 0
 *
 * Operators:
 *
 *     *       Any value
 *     */5     Every five units
 *     1       Exact value
 *     1-5     Inclusive range
 *     1,3,5   List
 *     1-10/2  Range with step
 *
 * Examples:
 *
 *     * * * * *
 *     Every minute.
 *
 *     */5 * * * *
 *     Every five minutes.
 *
 *     0 * * * *
 *     At minute zero of every hour.
 *
 *     30 4 * * 1-5
 *     04:30 Monday through Friday.
 *
 *     0 0 1 * *
 *     00:00 on the first day of every month.
 *
 *     0 0 1 */3 *
 *     00:00 on the first day of every third month.
 *
 * When both day-of-month and day-of-week are restricted, matching follows
 * traditional cron semantics: the two fields are combined using OR.
 */

/* -------------------------------------------------------------------------- */
/* Scheduler behaviour                                                        */
/* -------------------------------------------------------------------------- */

/**
 * Cron jobs are calendar-based and have minute-level precision.
 *
 * The implementation should:
 *
 *   1. Evaluate the current wall-clock minute.
 *   2. Ensure an occurrence is dispatched at most once.
 *   3. Avoid reparsing expressions during normal scheduler ticks.
 *   4. Detect backward clock jumps and avoid duplicate execution.
 *   5. Handle forward clock jumps without replaying an unbounded number of
 *      occurrences.
 *
 * The scheduler should normalize an expression when a job is registered.
 * Matching should operate on pre-parsed fields/bitmasks.
 *
 * A practical implementation may wake the scheduler every 0.5-1.0 seconds,
 * while cron matching itself remains minute-based.
 *
 * Jobs belong to the plugin that registered them. When a plugin is unloaded,
 * its jobs must be removed automatically.
 *
 * Map changes must not cause a job to execute twice for the same wall-clock
 * minute.
 */

/* -------------------------------------------------------------------------- */
/* Design notes for implementations                                           */
/* -------------------------------------------------------------------------- */

/**
 * Implementation notes:
 *
 * - Parse expressions only when they are created or changed.
 * - Represent each cron field as a compact bitmask where practical.
 * - Keep one scheduler tick for all jobs instead of one engine timer per job.
 * - Track the last processed calendar minute per job.
 * - Validate callback names during registration.
 * - Associate every job with its owner plugin.
 * - Do not execute Pawn callbacks from a worker thread.
 * - Keep default behaviour conservative: missed executions are skipped.
 * - Provide useful diagnostics for malformed expressions and callback errors.
 *
 * The public API is intentionally written as if cron were a normal AMX Mod X
 * library available to plugins. The implementation can be backed by an AMXX
 * module or by a Pawn library without requiring plugin authors to change the
 * API.
 */

Complete example:
/* -------------------------------------------------------------------------- */
/* Complete example                                                          */
/* -------------------------------------------------------------------------- */

#include <amxmodx>
#include <cron>

new g_daily_job;

public plugin_init()
{
    register_plugin(
        "Cron Example",
        "1.0.0",
        "hlds.run"
    );

    g_daily_job = cron_schedule_named(
        "daily_cleanup",
        "0 3 * * *",
        "cron_daily_cleanup"
    );

    cron_schedule_named(
        "five_minute_check",
        "*/5 * * * *",
        "cron_five_minute_check"
    );

    cron_schedule_named(
        "weekday_maintenance",
        "30 4 * * 1-5",
        "cron_weekday_maintenance"
    );
}

public cron_daily_cleanup(job_id)
{
    server_print("[CRON] Daily cleanup: #%d", job_id);
}

public cron_five_minute_check(job_id)
{
    server_print("[CRON] Five-minute check: #%d", job_id);
}

public cron_weekday_maintenance(job_id)
{
    server_print("[CRON] Weekday maintenance: #%d", job_id);
}

public plugin_end()
{
    // Optional. The scheduler automatically removes jobs owned by the
    // plugin, but explicit cleanup is useful when the plugin wants to stop
    // scheduling before it is unloaded.
    cron_cancel_all();
}
Сообщение автоматически объединено:

Task Scheduler - by JustinHoMi подойдёт под ваши нужды?
 
В чём конкретно заключается задача?

хорошо бы иметь какой-то подобный модуль или плагин
Сгенерировано ChatGPT (не имплементировано):
// vim: set ts=4 sw=4 tw=99 noet:
//
// HLDS Cron
// Copyright (C) hlds.run contributors.
//
// Cron scheduler API for AMX Mod X plugins.
//
// This include provides the public API for a cron scheduler. Include it in
// any plugin that needs wall-clock scheduling:
//
//     #include <cron>
//
// The scheduler uses the familiar five-field cron notation:
//
//     ┌──────── minute       0-59
//     │ ┌────── hour         0-23
//     │ │ ┌──── day of month 1-31
//     │ │ │ ┌── month        1-12
//     │ │ │ │ ┌ day of week 0-6 (Sunday = 0)
//     │ │ │ │ │
//     * * * * *
//
// Supported expressions:
//     *       any value
//     */n     every n units
//     a       exact value
//     a-b     inclusive range
//     a,b,c   list
//     a-b/n   range with step
//
// Examples:
//     */5 * * * *     Every five minutes
//     0 * * * *       Every hour
//     0 4 * * *       Every day at 04:00
//     30 3 * * 1-5    Weekdays at 03:30
//     0 0 1 * *       First day of every month
//
// Cron jobs use server local wall-clock time. Cron is intended for calendar
// schedules; use cron_every() for elapsed-time intervals.
//
// The API is deliberately small and follows the style of AMX Mod X include
// files: constants first, then public declarations, then detailed native
// documentation and examples.
//
// See the AMX Mod X module/include documentation for the native model and
// include conventions.

#if defined _cron_included
    #endinput
#endif
#define _cron_included

/**
 * No special scheduler flags.
 */
#define CRON_FLAG_NONE            0

/**
 * Run the job once immediately after registration, then continue normally.
 */
#define CRON_FLAG_RUN_ON_START    (1 << 0)

/**
 * Do not execute occurrences that were missed while the scheduler was not
 * running. This is the recommended default.
 */
#define CRON_FLAG_SKIP_MISSED     (1 << 1)

/**
 * Replay missed occurrences after the scheduler resumes.
 *
 * Implementations should protect against an excessive number of executions
 * with an internal replay limit.
 */
#define CRON_FLAG_REPLAY_MISSED   (1 << 2)

/**
 * Execute at the next matching cron occurrence and remove the job.
 */
#define CRON_FLAG_ONCE             (1 << 3)

/**
 * Result returned by cron_validate() and lifecycle functions.
 */
enum CronResult
{
    CRON_OK = 0,
    CRON_ERR_INVALID_EXPRESSION,
    CRON_ERR_INVALID_CALLBACK,
    CRON_ERR_INVALID_FLAGS,
    CRON_ERR_LIMIT_REACHED,
    CRON_ERR_NOT_FOUND,
    CRON_ERR_ALREADY_EXISTS,
    CRON_ERR_INTERNAL
};

/**
 * Current scheduler state.
 */
enum CronSchedulerState
{
    CRON_STATE_STOPPED = 0,
    CRON_STATE_RUNNING
};

/**
 * Creates a recurring cron job.
 *
 * The callback must be a public Pawn function with the following signature:
 *
 *     public my_callback(job_id)
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param callback
 *     Name of the public callback function.
 *
 * @param flags
 *     Combination of CRON_FLAG_* values.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @note The callback is executed in the normal AMX Mod X execution context.
 *       It must not perform long-running blocking work.
 *
 * @example
 *     public plugin_init()
 *     {
 *         cron_schedule("*/5 * * * *", "cron_five_minutes");
 *     }
 *
 *     public cron_five_minutes(job_id)
 *     {
 *         server_print("[CRON] job #%d", job_id);
 *     }
 */
native cron_schedule(const expression[], const callback[], flags = CRON_FLAG_SKIP_MISSED);

/**
 * Creates a recurring cron job with a stable human-readable name.
 *
 * Named jobs are useful for administration, diagnostics and idempotent
 * registration.
 *
 * @param name
 *     Unique job name, for example "daily_cleanup".
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param callback
 *     Name of the public callback function.
 *
 * @param flags
 *     Combination of CRON_FLAG_* values.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @note Job names are unique within the scheduler.
 *
 * @example
 *     public plugin_init()
 *     {
 *         cron_schedule_named(
 *             "daily_cleanup",
 *             "0 3 * * *",
 *             "cron_daily_cleanup"
 *         );
 *     }
 */
native cron_schedule_named(
    const name[],
    const expression[],
    const callback[],
    flags = CRON_FLAG_SKIP_MISSED
);

/**
 * Cancels a job.
 *
 * @param job_id
 *     Job ID returned by cron_schedule() or cron_schedule_named().
 *
 * @return
 *     true if the job existed and was cancelled.
 */
native bool:cron_cancel(job_id);

/**
 * Cancels a named job.
 *
 * @param name
 *     Name supplied to cron_schedule_named().
 *
 * @return
 *     true if the job existed and was cancelled.
 */
native bool:cron_cancel_named(const name[]);

/**
 * Checks whether a job exists.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     true if the job is active.
 */
native bool:cron_exists(job_id);

/**
 * Checks whether a named job exists.
 *
 * @param name
 *     Job name.
 *
 * @return
 *     true if the job is active.
 */
native bool:cron_exists_named(const name[]);

/**
 * Cancels all jobs owned by the calling plugin.
 *
 * @note The scheduler automatically removes jobs when their owning plugin
 *       is unloaded.
 */
native cron_cancel_all();

/**
 * Returns the number of active jobs owned by the calling plugin.
 *
 * @return
 *     Number of active jobs.
 */
native cron_count();

/**
 * Returns the total number of active jobs in the scheduler.
 *
 * @return
 *     Number of active jobs.
 */
native cron_total();

/**
 * Starts the scheduler.
 *
 * Normally the scheduler starts automatically. This function exists for
 * explicit lifecycle control and testing.
 *
 * @return
 *     CRON_OK on success.
 */
native CronResult:cron_start();

/**
 * Stops the scheduler without removing registered jobs.
 *
 * Starting it again resumes scheduling.
 *
 * @return
 *     CRON_OK on success.
 */
native CronResult:cron_stop();

/**
 * Returns the current scheduler state.
 *
 * @return
 *     CRON_STATE_STOPPED or CRON_STATE_RUNNING.
 */
native CronSchedulerState:cron_state();

/**
 * Validates a cron expression.
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param error
 *     Buffer receiving a human-readable error message.
 *
 * @param error_len
 *     Size of the error buffer.
 *
 * @return
 *     CRON_OK when valid, otherwise an appropriate CRON_ERR_* value.
 *
 * @example
 *     new error[128];
 *
 *     if (cron_validate("0 25 * * *", error, charsmax(error)) != CRON_OK)
 *     {
 *         server_print("[CRON] %s", error);
 *     }
 */
native CronResult:cron_validate(const expression[], error[], error_len);

/**
 * Calculates the next matching timestamp for an expression.
 *
 * @param expression
 *     Five-field cron expression.
 *
 * @param from_timestamp
 *     Unix timestamp from which the search starts. If 0, current server time
 *     is used.
 *
 * @return
 *     Unix timestamp of the next occurrence, or 0 when no occurrence exists.
 *
 * @example
 *     new timestamp = cron_next("0 4 * * *");
 *
 *     if (timestamp)
 *     {
 *         new date[32];
 *         format_time(date, charsmax(date), "%Y-%m-%d %H:%M:%S", timestamp);
 *         server_print("[CRON] next run: %s", date);
 *     }
 */
native cron_next(const expression[], from_timestamp = 0);

/**
 * Returns the timestamp of the last execution of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     Unix timestamp, or 0 if the job has never executed or does not exist.
 */
native cron_last_run(job_id);

/**
 * Returns the timestamp of the next execution of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     Unix timestamp, or 0 if the job does not exist.
 */
native cron_next_run(job_id);

/**
 * Gets the name of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_name(job_id, buffer[], buffer_len);

/**
 * Gets the cron expression of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_expression(job_id, buffer[], buffer_len);

/**
 * Gets the callback name of a job.
 *
 * @param job_id
 *     Job ID.
 *
 * @param buffer
 *     Destination buffer.
 *
 * @param buffer_len
 *     Destination buffer size.
 *
 * @return
 *     true when the job exists.
 */
native bool:cron_get_callback(job_id, buffer[], buffer_len);

/**
 * Immediately dispatches a job.
 *
 * Manual execution does not modify the cron schedule or next occurrence.
 *
 * @param job_id
 *     Job ID.
 *
 * @return
 *     true when the job was found and dispatched.
 *
 * @note This is intended for administration, testing and diagnostics.
 */
native bool:cron_trigger(job_id);

/**
 * Creates a one-shot elapsed-time job.
 *
 * @param delay
 *     Delay in seconds.
 *
 * @param callback
 *     Public callback name.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @example
 *     cron_once(30.0, "cron_after_thirty_seconds");
 *
 *     public cron_after_thirty_seconds(job_id)
 *     {
 *         server_print("[CRON] delayed task");
 *     }
 */
native cron_once(Float:delay, const callback[]);

/**
 * Creates a recurring elapsed-time job.
 *
 * Unlike cron_schedule(), this function is based on elapsed time rather than
 * calendar time.
 *
 * @param interval
 *     Interval in seconds.
 *
 * @param callback
 *     Public callback name.
 *
 * @return
 *     Positive job ID on success, 0 on failure.
 *
 * @example
 *     cron_every(60.0, "cron_every_minute");
 *
 *     public cron_every_minute(job_id)
 *     {
 *         server_print("[CRON] interval task");
 *     }
 */
native cron_every(Float:interval, const callback[]);

/**
 * Sets the scheduler log level.
 *
 * Suggested levels:
 *
 *     0 - errors only
 *     1 - normal
 *     2 - verbose/debug
 *
 * @param level
 *     Desired log level.
 */
native cron_set_log_level(level);

/* -------------------------------------------------------------------------- */
/* Callback contract                                                          */
/* -------------------------------------------------------------------------- */

/**
 * Cron callbacks receive exactly one argument: the job ID.
 *
 * Example:
 *
 *     public cron_daily_cleanup(job_id)
 *     {
 *         // Do a short, non-blocking operation.
 *     }
 *
 * The scheduler invokes callbacks synchronously. A callback should therefore
 * return quickly and should never wait for external I/O.
 */

/* -------------------------------------------------------------------------- */
/* Cron expression reference                                                  */
/* -------------------------------------------------------------------------- */

/**
 * Minute
 *
 *     0-59
 *
 * Hour
 *
 *     0-23
 *
 * Day of month
 *
 *     1-31
 *
 * Month
 *
 *     1-12
 *
 * Day of week
 *
 *     0-6
 *     Sunday = 0
 *
 * Operators:
 *
 *     *       Any value
 *     */5     Every five units
 *     1       Exact value
 *     1-5     Inclusive range
 *     1,3,5   List
 *     1-10/2  Range with step
 *
 * Examples:
 *
 *     * * * * *
 *     Every minute.
 *
 *     */5 * * * *
 *     Every five minutes.
 *
 *     0 * * * *
 *     At minute zero of every hour.
 *
 *     30 4 * * 1-5
 *     04:30 Monday through Friday.
 *
 *     0 0 1 * *
 *     00:00 on the first day of every month.
 *
 *     0 0 1 */3 *
 *     00:00 on the first day of every third month.
 *
 * When both day-of-month and day-of-week are restricted, matching follows
 * traditional cron semantics: the two fields are combined using OR.
 */

/* -------------------------------------------------------------------------- */
/* Scheduler behaviour                                                        */
/* -------------------------------------------------------------------------- */

/**
 * Cron jobs are calendar-based and have minute-level precision.
 *
 * The implementation should:
 *
 *   1. Evaluate the current wall-clock minute.
 *   2. Ensure an occurrence is dispatched at most once.
 *   3. Avoid reparsing expressions during normal scheduler ticks.
 *   4. Detect backward clock jumps and avoid duplicate execution.
 *   5. Handle forward clock jumps without replaying an unbounded number of
 *      occurrences.
 *
 * The scheduler should normalize an expression when a job is registered.
 * Matching should operate on pre-parsed fields/bitmasks.
 *
 * A practical implementation may wake the scheduler every 0.5-1.0 seconds,
 * while cron matching itself remains minute-based.
 *
 * Jobs belong to the plugin that registered them. When a plugin is unloaded,
 * its jobs must be removed automatically.
 *
 * Map changes must not cause a job to execute twice for the same wall-clock
 * minute.
 */

/* -------------------------------------------------------------------------- */
/* Design notes for implementations                                           */
/* -------------------------------------------------------------------------- */

/**
 * Implementation notes:
 *
 * - Parse expressions only when they are created or changed.
 * - Represent each cron field as a compact bitmask where practical.
 * - Keep one scheduler tick for all jobs instead of one engine timer per job.
 * - Track the last processed calendar minute per job.
 * - Validate callback names during registration.
 * - Associate every job with its owner plugin.
 * - Do not execute Pawn callbacks from a worker thread.
 * - Keep default behaviour conservative: missed executions are skipped.
 * - Provide useful diagnostics for malformed expressions and callback errors.
 *
 * The public API is intentionally written as if cron were a normal AMX Mod X
 * library available to plugins. The implementation can be backed by an AMXX
 * module or by a Pawn library without requiring plugin authors to change the
 * API.
 */

Complete example:
/* -------------------------------------------------------------------------- */
/* Complete example                                                          */
/* -------------------------------------------------------------------------- */

#include <amxmodx>
#include <cron>

new g_daily_job;

public plugin_init()
{
    register_plugin(
        "Cron Example",
        "1.0.0",
        "hlds.run"
    );

    g_daily_job = cron_schedule_named(
        "daily_cleanup",
        "0 3 * * *",
        "cron_daily_cleanup"
    );

    cron_schedule_named(
        "five_minute_check",
        "*/5 * * * *",
        "cron_five_minute_check"
    );

    cron_schedule_named(
        "weekday_maintenance",
        "30 4 * * 1-5",
        "cron_weekday_maintenance"
    );
}

public cron_daily_cleanup(job_id)
{
    server_print("[CRON] Daily cleanup: #%d", job_id);
}

public cron_five_minute_check(job_id)
{
    server_print("[CRON] Five-minute check: #%d", job_id);
}

public cron_weekday_maintenance(job_id)
{
    server_print("[CRON] Weekday maintenance: #%d", job_id);
}

public plugin_end()
{
    // Optional. The scheduler automatically removes jobs owned by the
    // plugin, but explicit cleanup is useful when the plugin wants to stop
    // scheduling before it is unloaded.
    cron_cancel_all();
}
Сообщение автоматически объединено:

Task Scheduler - by JustinHoMi подойдёт под ваши нужды?
Идея которую вы предложили очень даже хорошая, но я так понял plugin_init() выполняется каждую карту. Поэтому мне кажется идентификаторы задач нужно хранить в файле. И в проссе работы как-то проверять. Если о том, что нужно имплементировать.
А в том Task Scheduler такой прикол, что там нельзя задать например в начале каждого квартала.

Ну меня есть другая идея.

Попробовать зарегистрировать команду в amxx, в linux есть пакет cron.

И через rcon выполнять эту команду. То есть cron просто через rcon отправляет команду на сервер

Все, больше мне ничего в голову не приходит
 
мне кажется идентификаторы задач нужно хранить в файле
лучше опишите подробно какую конкретно задачу вы хотите решить этим CRON, в данный момент приходится догадываться, иначе мы будем отдаляться от решения проблемы раздумывая над изобретением костылей
 
лучше опишите подробно какую конкретно задачу вы хотите решить этим CRON, в данный момент приходится догадываться, иначе мы будем отдаляться от решения проблемы раздумывая над изобретением костылей
Если точнее каждое начало квартала сбрасывать некоторые значения в БД mysql, но hlds должен в реальном времени знать что сброшено.

Чтобы плагины знали о том, что произошел сброс некоторых значений в некоторых таблицах.

Допустим есть некоторые данные игрока, которые должны сбрасываться раз в квартал. И если игрок играет на сервере, то ему естественно нужно актуализировать данные в момент его игры
Например каждое начало квартала идет сброс очков, за эти очки можно покупать себе плюшки в магазине. И если игроку не актуализировать эти значения, он может себе приобрести плюшку, когда у него нет этих очков.
 
Классический cron не дает стопроцентной гарантии выполнения задачи, если сервер был выключен в назначенное время. Он лишь запускает задачи строго по текущему системному времени, полагаясь на непрерывную работу.

Я бы всё-таки отказался от реализации долгосрочного cron непосредственно внутри AMXX.

Даже если сделать проверку через ServerFrame() и на каждом тике сравнивать get_time() с временем следующего запуска — это решает только вопрос проверки времени, но не вопрос гарантированного выполнения.

Например:
C-подобный:
01.01 00:00 — задача должна выполниться
   ↓
HLDS DOWN
   ↓
02.01 — HLDS снова запущен
   ↓
ServerFrame() продолжает работать

Если логика не предусматривает отдельную обработку пропущенных задач, событие уже потеряно.

А если предусмотреть такую обработку, persistent state, retry, защиту от двойного запуска, восстановление после падения и подтверждение успешного выполнения — мы постепенно начинаем писать внутри AMXX собственный job scheduler.

Для критической задачи появляются требования вроде:
  • at-most-once — выполнить не более одного раза;
  • at-least-once — гарантировать повторную попытку;
  • exactly-once — фактически требует идемпотентности и сохранения состояния выполнения;
  • retry после ошибки;
  • recovery после downtime;
  • persistent last_executed / next_execution.
И это уже типичная задача для scheduler/job queue, а не игрового скрипта. В backend для подобных вещей существуют BullMQ и другие системы очередей.

При этом решение можно сделать очень простым и без сложной инфраструктуры:
C-подобный:
Linux cron / systemd timer
   ↓
небольшой скрипт
   ↓
MySQL / файл last_executed / status
   ↓
HLDS / AMXX
   ↓
игровая операция
Можно использовать обычный Linux cron, systemd timer, небольшой php/Node.js/Python-скрипт или, если подобных задач станет много, BullMQ на том же NestJS.

AMXX в этой архитектуре отвечает за то, как выполнить действие в игре, а внешний scheduler — за то, когда оно должно быть выполнено и не потеряется ли оно.

Поэтому ServerFrame() сам по себе не является аргументом в пользу реализации такого cron внутри AMXX. Он прекрасно решает polling, но не решает reliability.
 
Логика для пропущенных задач предусмотрена. Тоже на бэкенде (nestjs).
Стоит ли тогда ловить события через amxx socket?
 
Последнее редактирование модератором:

Кто просматривает тему

Назад
Верх