рдореИрдВ 3.1.20 (рд░реЗрдбрд┐рд╕ рдмреНрд░реЛрдХрд░ рдФрд░ рдмреИрдХрдПрдВрдб) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЬрдм рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдмрдВрдж рд╣реЛ рд░рд╣рд╛ рд╣реИ рддреЛ рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЪрд▓ рд░рд╣реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдирд┐рд░рд╕реНрдд/рдирд┐рд░рд╕реНрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рд╕рдВрднрд╡ рд╣реЛ рддреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ FAILED рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░реЗрдВ, рдФрд░ рдЕрдЧрд▓реА рдмрд╛рд░ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЗ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рдЙрдиреНрд╣реЗрдВ рдлрд┐рд░ рд╕реЗ рди рдЪрд▓рд╛рдПрдВред
рдореИрдВ рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдХрд╛рд░реНрдп рдЪрд▓рд╛ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдЪреВрдВрдХрд┐ рдХрд╛рд░реНрдп рдХрд╛ рджреБрд╖реНрдкреНрд░рднрд╛рд╡ рд╣реИ (рдФрд░ рдореИрдВ рдЗрд╕реЗ рдмрджрд▓ рдирд╣реАрдВ рд╕рдХрддрд╛), рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рдорд╛рд░рдирд╛ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛрдЧрд╛ рдЬрдм рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдореИрдВ рдирд╣реАрдВ рдЪрд╛рд╣рддрд╛ рдХрд┐ рдХрд╛рд░реНрдп рдХреЛ рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдпрд╛ рдЬрд╛рдП рдЬрдм рдореИрдВ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реВрдВ (рдореБрдЭреЗ рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реИ рдХрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕рд┐рдШрдВрдбрд▓рд░ рд╡реНрдпрд╡рд╣рд╛рд░ ...)
рдореИрдВрдиреЗ рд╕рдлрд▓рддрд╛ рдХреЗ рдмрд┐рдирд╛ http://stackoverflow.com/a/8230470 рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИред
рдФрд░ рдореИрдВрдиреЗ рдмреВрдЯрд╕реНрдЯреЗрдк рд╕реЗ рдирд┐рдпрдВрддреНрд░рдг рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдпрд╛ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреБрдЫ рдЪреАрдЬреЛрдВ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА:
from celery import Celery, bootsteps
from celery.task.control import revoke
# TODO : configuration for tests...
class BootPyrosNode(bootsteps.StartStopStep):
def __init__(self, worker, **kwargs):
logging.warn('{0!r} is starting from {1}'.format(worker, __file__))
[...]
def create(self, worker):
return self
def start(self, worker):
# our step is started together with all other Worker/Consumer
# bootsteps.
pass # not sure in which process this is run.
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting abort of current tasks...'.format(worker))
for req in worker.state.active_requests:
# worker.app.control.revoke(req.id, terminate=True) # not working
# revoke(req.id, terminate=True) # not working
self.node_proc.shutdown()
рдЗрд╕ рддрд░рд╣ рд╕реНрдерд╛рдкрд┐рдд:
celeros_app = Celery()
# setting up custom bootstep to start ROS node and pass ROS arguments to it
celeros_app.steps['worker'].add(BootPyrosNode)
celeros_app.user_options['worker'].add(Option('-R', '--ros-arg', action="append", help='Arguments for ros initialisation'))
рд╣рд╛рд▓рд╛рдВрдХрд┐ рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореЗрд░реЗ рдХрд╛рд░реНрдп рдХреЛ рдирд┐рд░рд╕реНрдд/рдирд┐рд░рд╕реНрдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, (рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд░реБрдХрдиреЗ рдХреЗ рдмрд╛рдж рдирд┐рдпрдВрддреНрд░рдг рд╕рдВрджреЗрд╢реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реЛ?) рдФрд░ рдореИрдВ рд╡рд┐рдЪрд╛рд░реЛрдВ рд╕реЗ рдмрд╛рд╣рд░ рд╣реЛ рд░рд╣рд╛ рд╣реВрдВред
рдпрджрд┐ рдЖрдк рдФрд░ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдХреЛрдб рдпрд╣рд╛рдВ рд╕реЗ рдЖрддрд╛ рд╣реИ: https://github.com/asmodehn/celerosред
рдХреНрдпрд╛ рдХреЛрдИ рд░рд╛рд╕реНрддрд╛ рд╣реИ, рдпрд╛ рдпрд╣ рдПрдХ рдЕрдиреБрдХреВрд▓рди рд╣реИ рдЬреЛ рдЕрднреА рддрдХ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ?
рдЖрдк рд╢рдЯрдбрд╛рдЙрди рдХреЗ рджреМрд░рд╛рди рдЕрдкрдиреЗ рдЖрдк рдХреЛ рд░рд┐рдореЛрдЯ рдХрдВрдЯреНрд░реЛрд▓ рдХрдорд╛рдВрдб рдирд╣реАрдВ рднреЗрдЬ рд╕рдХрддреЗ рд╣реИрдВ, рдЖрдкрдХреЛ рд╡рд░реНрдХрд░ рдЗрдВрдЯрд░реНрдирд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рджреЗрдЦреЗрдВ рдХрд┐ рд╕реЗрд▓реЗрд░реА/рд╡рд░реНрдХрд░/рдХрдВрдЯреНрд░реЛрд▓.py рдореЗрдВ рд░рд┐рдореЛрдЯ рдХрдВрдЯреНрд░реЛрд▓ рдХрдорд╛рдВрдб рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред
рдЖрдкрдХреЛ рд╢рд╛рдпрдж рдпрд╣ рднреА рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдЖрдкрдХрд╛ рдмреВрдЯрд╕реНрдЯреЗрдк рдкреВрд▓ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рд╢рдЯрдбрд╛рдЙрди рдХреЗ рджреМрд░рд╛рди рдЖрдкрдХреА stop()
рд╡рд┐рдзрд┐ рдХреЛ рдкрд╣рд▓реЗ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ:
class Step..:
requires = ('celery.worker.components:Pool',)
рдзрдиреНрдпрд╡рд╛рдж !
рдореИрдВ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд╢рдЯрдбрд╛рдЙрди рдкрд░ рдЪрд▓ рд░рд╣реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред :
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting termination of current tasks...'.format(worker))
# Following code from worker.control.revoke
task_ids = []
terminated = set()
# cleaning all reserved tasks since we are shutting down
signum = _signals.signum('TERM')
for request in [r for r in worker.state.reserved_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum)
# Aborting currently running tasks, and triggering soft timeout exception to allow task to clean up.
signum = _signals.signum('USR1')
for request in [r for r in worker.state.active_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum) # triggering SoftTimeoutException in Task
if terminated:
terminatedstr = ', '.join(task_ids)
logger.info('Tasks flagged as revoked: %s', terminatedstr)
self.node_proc.shutdown()
рдкрд╣рд▓реЗ рдореИрдВ рдХрд┐рд╕реА рднреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд╛рд░реНрдп рдХреЛ рд╢рдЯрдбрд╛рдЙрди рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ рд▓реЗрдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд░рдХреНрд╖рд┐рдд_рдЕрдиреБрд░реЛрдз рд╕реВрдЪреА рдореЗрдВ рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░ рджреЗрддрд╛ рд╣реВрдВред
рдлрд┐рд░ рдореИрдВ рд╕рдХреНрд░рд┐рдп рдЕрдиреБрд░реЛрдз рдХреЛ рдирд┐рд░рд╕реНрдд рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдлрд┐рд░ рдореИрдВ рдХрд╛рд░реНрдп рдореЗрдВ рдПрдХ рд╕рдлрд╛рдИ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдореЗрдВ SoftTimeLimitExceeded рдЕрдкрд╡рд╛рдж рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реВрдВред рдЪреВрдВрдХрд┐ рдореИрдВ acks_late (рдПрдХ рд╕рдордп рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рд░реНрдп рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдореБрдЭреЗ рдЗрд╕реЗ рдареАрдХ рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╕реЗ рд╡рд╛рдкрд╕ рд▓реМрдЯрдиреЗ рдпрд╛ рдмрдврд╝рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд▓реА рдмрд╛рд░ рдЬрдм рдореИрдВ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдЗрд╕реЗ рдкреБрдирд░рд╛рд░рдВрдн рдирд╣реАрдВ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред
рдореИрдВ рдирд┐рд░рд╕реНрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЬрдм рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдмреВрдЭрдХрд░ рдХрд┐рд╕реА рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдирд┐рд░рд╕реНрдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдХреЛрдбрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдХреБрдЫ рдЬрдЯрд┐рд▓/рд▓рдВрдмреА рд╕рдлрд╛рдИ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рдорд╛рдорд▓рд╛ рдЕрдзрд┐рдХ рд╣реИ рдЬреИрд╕реЗ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдмрдВрдж рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдореИрдВ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд╡рд┐рдлрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдореЗрдВ рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рдПрдХ рдЙрдЪрд┐рдд рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛?
рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХрд╛рд░реНрдп рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ ... рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП on_revoke() рдпрд╛ on_abort() рд╡рд┐рдзрд┐ рдХреЛ рдЕрдзрд┐рднрд╛рд░рд┐рдд рдХрд░реЗрдВред рдФрд░ рд╢рд╛рдпрдж рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдирд┐рд░рд╕реНрдд рдХрд░рдиреЗ рдкрд░ рдПрдХрд╛рдзрд┐рдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ ...
рдмрд╕ рдореЗрд░реЗ 2 рд╕реЗрдВрдЯ, рдореИрдВрдиреЗ рдЕрднреА рддрдХ рд╕реЗрд▓реЗрд░реА v4.0 рдХреА рдЬрд╛рдБрдЪ рдирд╣реАрдВ рдХреА рд╣реИред
рдЗрд╕ рдкрд░ рдХрд┐рд╕реА рднреА рдЕрджреНрдпрддрди?
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдзрдиреНрдпрд╡рд╛рдж !
рдореИрдВ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рд╢рдЯрдбрд╛рдЙрди рдкрд░ рдЪрд▓ рд░рд╣реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред :
рдкрд╣рд▓реЗ рдореИрдВ рдХрд┐рд╕реА рднреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд╛рд░реНрдп рдХреЛ рд╢рдЯрдбрд╛рдЙрди рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ рд▓реЗрдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд░рдХреНрд╖рд┐рдд_рдЕрдиреБрд░реЛрдз рд╕реВрдЪреА рдореЗрдВ рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░ рджреЗрддрд╛ рд╣реВрдВред
рдлрд┐рд░ рдореИрдВ рд╕рдХреНрд░рд┐рдп рдЕрдиреБрд░реЛрдз рдХреЛ рдирд┐рд░рд╕реНрдд рдХрд░рддрд╛ рд╣реВрдВ, рдФрд░ рдлрд┐рд░ рдореИрдВ рдХрд╛рд░реНрдп рдореЗрдВ рдПрдХ рд╕рдлрд╛рдИ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдореЗрдВ SoftTimeLimitExceeded рдЕрдкрд╡рд╛рдж рдХреЛ рдЯреНрд░рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реВрдВред рдЪреВрдВрдХрд┐ рдореИрдВ acks_late (рдПрдХ рд╕рдордп рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рд░реНрдп рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдореБрдЭреЗ рдЗрд╕реЗ рдареАрдХ рд╕реЗ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рд╕реЗ рд╡рд╛рдкрд╕ рд▓реМрдЯрдиреЗ рдпрд╛ рдмрдврд╝рд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд▓реА рдмрд╛рд░ рдЬрдм рдореИрдВ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рддрд╛ рд╣реВрдВ рддреЛ рдЗрд╕реЗ рдкреБрдирд░рд╛рд░рдВрдн рдирд╣реАрдВ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред
рдореИрдВ рдирд┐рд░рд╕реНрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЬрдм рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдмреВрдЭрдХрд░ рдХрд┐рд╕реА рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдирд┐рд░рд╕реНрдд рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдХреЛрдбрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдХреБрдЫ рдЬрдЯрд┐рд▓/рд▓рдВрдмреА рд╕рдлрд╛рдИ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ рдорд╛рдорд▓рд╛ рдЕрдзрд┐рдХ рд╣реИ рдЬреИрд╕реЗ рдХрд╛рд░реНрдпрдХрд░реНрддрд╛ рдмрдВрдж рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдореИрдВ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд╡рд┐рдлрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдЬрд╡рд╛рдЗрди рдореЗрдВ рдЪреАрдЬреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рдПрдХ рдЙрдЪрд┐рдд рддрд░реАрдХрд╛ рд╣реЛрдЧрд╛?
рднрд╡рд┐рд╖реНрдп рдХреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдХрд╛рд░реНрдп рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ ... рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП on_revoke() рдпрд╛ on_abort() рд╡рд┐рдзрд┐ рдХреЛ рдЕрдзрд┐рднрд╛рд░рд┐рдд рдХрд░реЗрдВред рдФрд░ рд╢рд╛рдпрдж рдХреБрдЫ рд╢рд░реНрддреЛрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдирд┐рд░рд╕реНрдд рдХрд░рдиреЗ рдкрд░ рдПрдХрд╛рдзрд┐рдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ ...
рдмрд╕ рдореЗрд░реЗ 2 рд╕реЗрдВрдЯ, рдореИрдВрдиреЗ рдЕрднреА рддрдХ рд╕реЗрд▓реЗрд░реА v4.0 рдХреА рдЬрд╛рдБрдЪ рдирд╣реАрдВ рдХреА рд╣реИред