forked from goodboy/tractor
				
			Reduce "ignore cases" script to `trio`-only
Remove all the `tractor` usage (with IPC ctxs) and just get us a min-reproducing-example with a multi-task-single `trio.Lock`. The wrapping test suite runs the exact same with an ignore case and an `.xfail()` for when we let the `trio.WouldBlock` be unmasked.remotes/1757891924488435790/main
							parent
							
								
									9c6b90ef04
								
							
						
					
					
						commit
						07781e38cd
					
				|  | @ -1,3 +1,6 @@ | |||
| from contextlib import ( | ||||
|     asynccontextmanager as acm, | ||||
| ) | ||||
| from functools import partial | ||||
| 
 | ||||
| import tractor | ||||
|  | @ -8,87 +11,72 @@ log = tractor.log.get_logger( | |||
|     name=__name__ | ||||
| ) | ||||
| 
 | ||||
| _lock: trio.Lock|None = None | ||||
| 
 | ||||
| 
 | ||||
| @acm | ||||
| async def acquire_singleton_lock( | ||||
|     _lock = trio.Lock(), | ||||
| ) -> None: | ||||
|     global _lock | ||||
|     if _lock is None: | ||||
|         log.info('Allocating LOCK') | ||||
|         _lock = trio.Lock() | ||||
| 
 | ||||
|     log.info('TRYING TO LOCK ACQUIRE') | ||||
|     await _lock.acquire() | ||||
|     log.info('ACQUIRED') | ||||
|     async with _lock: | ||||
|         log.info('ACQUIRED') | ||||
|         yield _lock | ||||
| 
 | ||||
|     log.info('RELEASED') | ||||
| 
 | ||||
| 
 | ||||
| @tractor.context | ||||
| async def acquire_actor_global_lock( | ||||
|     ctx: tractor.Context, | ||||
| 
 | ||||
|     ignore_special_cases: bool, | ||||
| async def hold_lock_forever( | ||||
|     task_status=trio.TASK_STATUS_IGNORED | ||||
| ): | ||||
|     if not ignore_special_cases: | ||||
|         from tractor.trionics import _taskc | ||||
|         _taskc._mask_cases.clear() | ||||
| 
 | ||||
|     await acquire_singleton_lock() | ||||
|     await ctx.started('locked') | ||||
| 
 | ||||
|     # block til cancelled | ||||
|     await trio.sleep_forever() | ||||
|     async with ( | ||||
|         tractor.trionics.maybe_raise_from_masking_exc(), | ||||
|         acquire_singleton_lock() as lock, | ||||
|     ): | ||||
|         task_status.started(lock) | ||||
|         await trio.sleep_forever() | ||||
| 
 | ||||
| 
 | ||||
| async def main( | ||||
|     ignore_special_cases: bool, | ||||
|     loglevel: str = 'info', | ||||
|     debug_mode: bool = True, | ||||
| 
 | ||||
|     _fail_after: float = 2, | ||||
| ): | ||||
|     tractor.log.get_console_log(level=loglevel) | ||||
|     async with ( | ||||
|         trio.open_nursery() as tn, | ||||
| 
 | ||||
|     with trio.fail_after(_fail_after): | ||||
|         async with ( | ||||
|             tractor.trionics.collapse_eg(), | ||||
|             tractor.open_nursery( | ||||
|                 debug_mode=debug_mode, | ||||
|                 loglevel=loglevel, | ||||
|             ) as an, | ||||
|             trio.open_nursery() as tn, | ||||
|         ): | ||||
|             ptl = await an.start_actor( | ||||
|                 'locker', | ||||
|                 enable_modules=[__name__], | ||||
|         # tractor.trionics.maybe_raise_from_masking_exc() | ||||
|         # ^^^ XXX NOTE, interestingly putting the unmasker | ||||
|         # here does not exhibit the same behaviour ?? | ||||
|     ): | ||||
|         if not ignore_special_cases: | ||||
|             from tractor.trionics import _taskc | ||||
|             _taskc._mask_cases.clear() | ||||
| 
 | ||||
|         _lock = await tn.start( | ||||
|             hold_lock_forever, | ||||
|         ) | ||||
|         with trio.move_on_after(0.2): | ||||
|             await tn.start( | ||||
|                 hold_lock_forever, | ||||
|             ) | ||||
| 
 | ||||
|             async def _open_ctx( | ||||
|                 task_status=trio.TASK_STATUS_IGNORED, | ||||
|             ): | ||||
|                 async with ptl.open_context( | ||||
|                     acquire_actor_global_lock, | ||||
|                     ignore_special_cases=ignore_special_cases, | ||||
|                 ) as pair: | ||||
|                     task_status.started(pair) | ||||
|                     await trio.sleep_forever() | ||||
| 
 | ||||
|             first_ctx, first = await tn.start(_open_ctx,) | ||||
|             assert first == 'locked' | ||||
| 
 | ||||
|             with trio.move_on_after(0.5):# as cs: | ||||
|                 await _open_ctx() | ||||
| 
 | ||||
|             # await tractor.pause() | ||||
|             print('cancelling first IPC ctx!') | ||||
|             await first_ctx.cancel() | ||||
| 
 | ||||
|             await ptl.cancel_actor() | ||||
|             # await tractor.pause() | ||||
|         tn.cancel_scope.cancel() | ||||
| 
 | ||||
| 
 | ||||
| # XXX, manual test as script | ||||
| if __name__ == '__main__': | ||||
|     tractor.log.get_console_log(level='info') | ||||
|     for case in [False, True]: | ||||
|     for case in [True, False]: | ||||
|         log.info( | ||||
|             f'\n' | ||||
|             f'------ RUNNING SCRIPT TRIAL ------\n' | ||||
|             f'child_errors_midstream: {case!r}\n' | ||||
|             f'ignore_special_cases: {case!r}\n' | ||||
|         ) | ||||
|         trio.run(partial( | ||||
|             main, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue