async def main(): async with Golem(budget=1.0, subnet_tag="devnet-beta") as golem: cluster = await golem.run_service(DateService, num_instances=1) start_time = datetime.now() while datetime.now() < start_time + timedelta(minutes=1): for num, instance in enumerate(cluster.instances): print( f"Instance {num} is {instance.state.value} on {instance.provider_name}" ) await asyncio.sleep(REFRESH_INTERVAL_SEC)
async def test_emit_event_class(dummy_yagna_engine): got_events_1 = [] got_events_2 = [] got_events_3 = [] def event_consumer_1(event: events.Event): got_events_1.append(event) def event_consumer_2(event: events.Event): got_events_2.append(event) def event_consumer_3(event: events.Event): got_events_3.append(event) golem = Golem(budget=1, app_key="NOT_A_REAL_APPKEY") golem.add_event_consumer(event_consumer_1, [events.SubscriptionEvent]) golem.add_event_consumer(event_consumer_2, [events.TaskEvent, "ServiceEvent"]) golem.add_event_consumer(event_consumer_3) async with golem: invoice_received = golem._engine.emit(events.InvoiceReceived, job="foo", agreement="bar", invoice="baz") subscription_created = golem._engine.emit(events.SubscriptionCreated, job="foo", subscription="bar") service_finished = golem._engine.emit(events.ServiceFinished, job="foo", agreement="bar", activity="baz", service="???") task_started = golem._engine.emit(events.TaskStarted, job="foo", agreement="bar", activity="baz", task="???") assert got_events_1 == [subscription_created] assert got_events_2 == [service_finished, task_started] # Additional ShutdownFinished event is passed to the catchall consumer only assert got_events_3[:4] == [ invoice_received, subscription_created, service_finished, task_started, ] assert len(got_events_3) == 5 and isinstance(got_events_3[4], events.ShutdownFinished)
async def main(): package = await vm.repo( image_hash="d646d7b93083d817846c2ae5c62c72ca0507782385a2e29291a3d376", ) tasks = [Task(data=None)] async with Golem(budget=1.0, subnet_tag="devnet-beta") as golem: async for completed in golem.execute_tasks(worker, tasks, payload=package): print(completed.result.stdout)
async def main(): vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) async def worker(work_ctx, tasks): async for task in tasks: script = work_ctx.new_script() print("task data:", task.data, file=sys.stderr) script.run("/bin/sleep", "1") yield script task.accept_result(result=task.data) async with Golem( budget=10.0, subnet_tag="goth", event_consumer=log_event_repr, ) as golem: # We use an async task generator that yields tasks removed from # an async queue. Each computed task will potentially spawn # new tasks -- this is made possible thanks to using async task # generator as an input to `executor.submit()`. task_queue = asyncio.Queue() # Seed the queue with the first task: await task_queue.put(Task(data=3)) async def input_generator(): """Task generator yields tasks removed from `queue`.""" while True: task = await task_queue.get() if task.data == 0: break yield task async for task in golem.execute_tasks( worker, input_generator(), vm_package, max_workers=1, timeout=timedelta(minutes=6), ): print("task result:", task.result, file=sys.stderr) for n in range(task.result): await task_queue.put(Task(data=task.result - 1)) print("all done!", file=sys.stderr)
async def test_emit_event(dummy_yagna_engine): got_events_1 = [] got_events_2 = [] got_events_3 = [] got_events_4 = [] def event_consumer_1(event: events.Event) -> None: # Event consumer passed to Golem() got_events_1.append(event) def event_consumer_2(event: events.Event) -> None: # Event consumer passed via add_event_consumer to not-yet-started Golem got_events_2.append(event) def event_consumer_3(event: events.Event) -> None: # Event consumer passed to working Golem got_events_3.append(event) golem = Golem(budget=1, event_consumer=event_consumer_1, app_key="NOT_A_REAL_APPKEY") golem.add_event_consumer(event_consumer_2) async with golem: golem.add_event_consumer(event_consumer_3) for sample_event in sample_events: event_class, event_kwargs = type(sample_event), asdict( sample_event) del event_kwargs["timestamp"] # timestamp is set only internally emitted_event = golem._engine.emit(event_class, **event_kwargs) got_events_4.append(emitted_event) assert got_events_1 == emitted_events assert got_events_2 == emitted_events assert got_events_3 == emitted_events assert got_events_4 == sample_events # When exiting from golem contextmanager, new `_Engine` is created -> we must ensure # event consumers are not lost when `_Engine` exits -> so we repeat the same test again got_events_1.clear() got_events_2.clear() got_events_3.clear() got_events_4.clear() async with golem: for sample_event in sample_events: event_class, event_kwargs = type(sample_event), asdict( sample_event) del event_kwargs["timestamp"] # timestamp is set only internally emitted_event = golem._engine.emit(event_class, **event_kwargs) got_events_4.append(emitted_event) assert got_events_1 == emitted_events assert got_events_2 == emitted_events assert got_events_3 == emitted_events assert got_events_4 == sample_events
async def main(): async with Golem(budget=1.0, subnet_tag="goth") as golem: # Start a cluster with a single service. # The first instance will fail before reaching the `running` state # due to an error. Another instance should be spawned in its place. log("Starting cluster...") await golem.run_service(FirstInstanceFailsToStart) # This another instance should get to `running` state. while not instances_running: log("Waiting for an instance...") await asyncio.sleep(2) # And then stop. while not instances_stopped: log("Waiting until the instance stops...") await asyncio.sleep(2) # Then we start another cluster with a single instance. # This time the instance is stopped by a signal before it reaches the `running` state, # but in that case the cluster should not spawn another instance. log("Starting another cluster...") cluster = await golem.run_service(FirstInstanceFailsToStart) while instances_started < 3: log("Waiting for another instance...") await asyncio.sleep(2) assert [i for i in cluster.instances if i.is_available] log("Closing the second cluster...") cluster.stop() while [i for i in cluster.instances if i.is_available]: log("Waiting for the cluster to stop...") await asyncio.sleep(2) log("Cluster stopped")
async def main(running_time_sec, subnet_tag, driver=None, network=None): # necessary to set maximum price for one unit of custom counter, # default strategy does not take custom counter prices into account strategy = LeastExpensiveLinearPayuMS( max_price_for={ com.Counter.CPU.value: Decimal("0.2"), com.Counter.TIME.value: Decimal("0.1"), "golem.usage.custom.counter": Decimal("0.1"), }) async with Golem( budget=10.0, subnet_tag=subnet_tag, payment_driver=driver, payment_network=network, strategy=strategy, ) as golem: instance_params = [{"running_time_sec": running_time_sec}] cluster = await golem.run_service(CustomCounterService, instance_params=instance_params) def print_instances(): print( f"instances: {[{s.id, s.state.value} for s in cluster.instances]}" ) was_running = False while True: await asyncio.sleep(3) if was_running and all([ s.state == ServiceState.terminated for s in cluster.instances ]): print_instances() print("All services were successfully terminated") break if len(cluster.instances) > 0: print_instances() was_running = True
async def main(): package = await vm.repo( image_hash="d646d7b93083d817846c2ae5c62c72ca0507782385a2e29291a3d376") tasks = [Task(data=None)] timeout = timedelta(hours=24) async with Golem( budget=10.0, strategy=ShortDebitNoteIntervalAndPaymentTimeout(), subnet_tag="goth", event_consumer=log_event_repr, ) as golem: logger = logging.getLogger("yapapi") logger.handlers[0].setLevel(logging.DEBUG) async for completed in golem.execute_tasks(worker, tasks, payload=package, max_workers=1, timeout=timeout): print(f"Task finished: {completed}.")
async def main(subnet_tag, payment_driver=None, payment_network=None, num_instances=2): # By passing `event_consumer=log_summary()` we enable summary logging. # See the documentation of the `yapapi.log` module on how to set # the level of detail and format of the logged information. async with Golem( budget=1.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print_env_info(golem) network = await golem.create_network("192.168.0.1/24") async with network: cluster = await golem.run_service(SshService, network=network, num_instances=num_instances) instances = cluster.instances while True: print(instances) try: await asyncio.sleep(5) except (KeyboardInterrupt, asyncio.CancelledError): break cluster.stop() cnt = 0 while cnt < 3 and any(s.is_available for s in instances): print(instances) await asyncio.sleep(5) cnt += 1
async def main(subnet_tag, payment_driver=None, payment_network=None): package = await vm.repo( image_hash="a23ce2c0c29ea9711e4a293a2805700e2f0cb6450fddf9506812eb1b", min_mem_gib=0.5, min_storage_gib=2.0, ) tasks = [() for _ in range(10)] async def worker(ctx: WorkContext, tasks): async for task in tasks: output_file = f"output_{datetime.now()}_{random.random()}.txt" script = ctx.new_script(timeout=timedelta(minutes=10)) script.run("/usr/bin/stress-ng", "--cpu", "1", "--timeout", "1") script.run("/golem/task.sh", "-o", "1024", "-t", "5") script.run("/golem/task.sh", "-f", "/golem/output/output.txt,1048576") script.download_file(f"/golem/output/output.txt", output_file) script.run("/golem/task.sh", "-e", "1024", "-t", "5") try: yield script task.accept_result(result=output_file) except BatchTimeoutError: print( f"{TEXT_COLOR_RED}" f"Task {task} timed out on {ctx.provider_name}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") raise async with Golem( budget=10.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print( f"yapapi version: {TEXT_COLOR_YELLOW}{yapapi_version}{TEXT_COLOR_DEFAULT}\n" f"Using subnet: {TEXT_COLOR_YELLOW}{subnet_tag}{TEXT_COLOR_DEFAULT}, " f"payment driver: {TEXT_COLOR_YELLOW}{golem.payment_driver}{TEXT_COLOR_DEFAULT}, " f"and network: {TEXT_COLOR_YELLOW}{golem.payment_network}{TEXT_COLOR_DEFAULT}\n" ) num_tasks = 0 start_time = datetime.now() completed_tasks = golem.execute_tasks( worker, [Task(data=data) for data in tasks], payload=package, max_workers=50, timeout=timedelta(minutes=30), ) async for task in completed_tasks: num_tasks += 1 print( f"{TEXT_COLOR_CYAN}" f"Task computed: {task}, result: {task.result}, time: {task.running_time}" f"{TEXT_COLOR_DEFAULT}") print( f"{TEXT_COLOR_CYAN}" f"{num_tasks} tasks computed, total time: {datetime.now() - start_time}" f"{TEXT_COLOR_DEFAULT}")
if __name__ == "__main__": parser = build_parser("Render a Blender scene") parser.add_argument("--show-usage", action="store_true", help="show activity usage and cost") parser.add_argument( "--min-cpu-threads", type=int, default=2, help="require the provider nodes to have at least this number of available CPU threads", ) now = datetime.now().strftime("%Y-%m-%d_%H.%M.%S") parser.set_defaults(log_file=f"blender-yapapi-{now}.log") args = parser.parse_args() golem = Golem( budget=10, subnet_tag=args.subnet_tag, payment_driver=args.payment_driver, payment_network=args.payment_network, ) run_golem_example( main( golem, show_usage=args.show_usage, min_cpu_threads=args.min_cpu_threads, ), log_file=args.log_file, )
async def main(subnet_tag, payment_driver, payment_network, port): async with Golem( budget=1.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print_env_info(golem) network = await golem.create_network("192.168.0.1/24") async with network: db_cluster = await golem.run_service(DbService, network=network) db_instance = db_cluster.instances[0] def still_starting(cluster): return any(i.state in (ServiceState.pending, ServiceState.starting) for i in cluster.instances) def raise_exception_if_still_starting(cluster): if still_starting(cluster): raise Exception( f"Failed to start {cluster} instances " f"after {STARTING_TIMEOUT.total_seconds()} seconds") commissioning_time = datetime.now() while (still_starting(db_cluster) and datetime.now() < commissioning_time + STARTING_TIMEOUT): print(db_cluster.instances) await asyncio.sleep(5) raise_exception_if_still_starting(db_cluster) print( f"{TEXT_COLOR_CYAN}DB instance started, spawning the web server{TEXT_COLOR_DEFAULT}" ) web_cluster = await golem.run_service( HttpService, network=network, instance_params=[{ "db_address": db_instance.network_node.ip }], ) # wait until all remote http instances are started while (still_starting(web_cluster) and datetime.now() < commissioning_time + STARTING_TIMEOUT): print(web_cluster.instances + db_cluster.instances) await asyncio.sleep(5) raise_exception_if_still_starting(web_cluster) # service instances started, start the local HTTP server proxy = LocalHttpProxy(web_cluster, port) await proxy.run() print( f"{TEXT_COLOR_CYAN}Local HTTP server listening on:\nhttp://localhost:{port}{TEXT_COLOR_DEFAULT}" ) # wait until Ctrl-C while True: print(web_cluster.instances + db_cluster.instances) try: await asyncio.sleep(10) except (KeyboardInterrupt, asyncio.CancelledError): break # perform the shutdown of the local http server and the service cluster await proxy.stop() print(f"{TEXT_COLOR_CYAN}HTTP server stopped{TEXT_COLOR_DEFAULT}") web_cluster.stop() db_cluster.stop() cnt = 0 while cnt < 3 and any( s.is_available for s in web_cluster.instances + db_cluster.instances): print(web_cluster.instances + db_cluster.instances) await asyncio.sleep(5) cnt += 1
async def main(args): package = await vm.repo( image_hash="055911c811e56da4d75ffc928361a78ed13077933ffa8320fb1ec2db", min_mem_gib=0.5, min_storage_gib=2.0, ) async with Golem( budget=10.0, subnet_tag=args.subnet_tag, payment_driver=args.payment_driver, payment_network=args.payment_network, ) as golem: print_env_info(golem) start_time = datetime.now() completed = golem.execute_tasks( compute_keyspace, [Task(data="compute_keyspace")], payload=package, timeout=KEYSPACE_TIMEOUT_ALL_TASKS, ) keyspace = 0 async for task in completed: keyspace = task.result print( f"{TEXT_COLOR_CYAN}" f"Task computed: keyspace size count. The keyspace size is {keyspace}" f"{TEXT_COLOR_DEFAULT}" ) data = (Task(data=c) for c in range(0, keyspace, args.chunk_size)) max_workers = args.max_workers or math.ceil(keyspace / args.chunk_size) // 2 completed = golem.execute_tasks( perform_mask_attack, data, payload=package, max_workers=max_workers, timeout=MASK_ATTACK_TIMEOUT, ) password = None async for task in completed: print( f"{TEXT_COLOR_CYAN}Task computed: {task}, result: {task.result}{TEXT_COLOR_DEFAULT}" ) result = _parse_result(task.result) if result: password = result if password: print(f"{TEXT_COLOR_GREEN}Password found: {password}{TEXT_COLOR_DEFAULT}") else: print(f"{TEXT_COLOR_RED}No password found{TEXT_COLOR_DEFAULT}") print(f"{TEXT_COLOR_CYAN}Total time: {datetime.now() - start_time}{TEXT_COLOR_DEFAULT}")
async def main(subnet_tag, payment_driver, payment_network, num_instances, port, running_time): async with Golem( budget=1.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print_env_info(golem) commissioning_time = datetime.now() network = await golem.create_network("192.168.0.1/24") cluster = await golem.run_service( HttpService, network=network, num_instances=num_instances, expiration=datetime.now(timezone.utc) + STARTING_TIMEOUT + EXPIRATION_MARGIN + timedelta(seconds=running_time), ) instances = cluster.instances def still_starting(): return any(i.state in (ServiceState.pending, ServiceState.starting) for i in instances) # wait until all remote http instances are started while still_starting() and datetime.now() < commissioning_time + STARTING_TIMEOUT: print(f"instances: {instances}") await asyncio.sleep(5) if still_starting(): raise Exception( f"Failed to start instances after {STARTING_TIMEOUT.total_seconds()} seconds" ) # service instances started, start the local HTTP server proxy = LocalHttpProxy(cluster, port) await proxy.run() print( f"{TEXT_COLOR_CYAN}Local HTTP server listening on:\nhttp://localhost:{port}{TEXT_COLOR_DEFAULT}" ) # wait until Ctrl-C start_time = datetime.now() while datetime.now() < start_time + timedelta(seconds=running_time): print(instances) try: await asyncio.sleep(10) except (KeyboardInterrupt, asyncio.CancelledError): break # perform the shutdown of the local http server and the service cluster await proxy.stop() print(f"{TEXT_COLOR_CYAN}HTTP server stopped{TEXT_COLOR_DEFAULT}") cluster.stop() cnt = 0 while cnt < 3 and any(s.is_available for s in instances): print(instances) await asyncio.sleep(5) cnt += 1 await network.remove()
async def test_incorrect_event_class_str(): golem = Golem(budget=1, app_key="NOT_A_REAL_APPKEY") with pytest.raises(ValueError): golem.add_event_consumer(lambda event: event, ["NoSuchEvent"])
async def main(): vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) first_task = True async def duplicator(work_ctx, tasks): """A worker that executes `echo {task.data} {task.data}` command on provider. The command's output is the result of the whole task. The first ever task computed by an instance of this worker fails. It succeeds when re-tried. This may be used to test re-trying tasks, creating new agreements and displaying summary information on task/activity failures. """ async for task in tasks: nonlocal first_task script = work_ctx.new_script() if first_task: first_task = False script.run("/bin/sleep", "1") script.run("/command/not/found") script.run("/bin/sleep", "1") future_result = script.run("/bin/echo", task.data, task.data) yield script result = await future_result output = result.stdout.strip() task.accept_result(output) async with Golem(budget=1.0, subnet_tag="goth") as golem: # Construct a pipeline: # # input_tasks # | # V # [ Job ALEF ] # | # V # intermediate_tasks # | # V # [ Job BET ] # | # V # output_tasks input_tasks = [Task(s) for s in "01234567"] computed_input_tasks = golem.execute_tasks( duplicator, input_tasks, payload=vm_package, max_workers=1, job_id="ALEF", ) async def intermediate_tasks(): async for task in computed_input_tasks: print(f"ALEF computed task: {task.data} -> {task.result}", file=sys.stderr) yield Task(data=task.result) output_tasks = golem.execute_tasks( duplicator, intermediate_tasks(), payload=vm_package, max_workers=1, job_id="BET", ) async for task in output_tasks: print(f"BET computed task: {task.data} -> {task.result}", file=sys.stderr)
async def main( subnet_tag, running_time, payment_driver=None, payment_network=None, num_instances=1, show_usage=False, ): async with Golem( budget=1.0, subnet_tag=subnet_tag, payment_driver=payment_driver, payment_network=payment_network, ) as golem: print_env_info(golem) commissioning_time = datetime.now() # start the service cluster = await golem.run_service( SimpleService, instance_params=[ {"instance_name": f"simple-service-{i+1}", "show_usage": show_usage} for i in range(num_instances) ], expiration=datetime.now(timezone.utc) + STARTING_TIMEOUT + EXPIRATION_MARGIN + timedelta(seconds=running_time), ) print(f"{TEXT_COLOR_YELLOW}" f"Starting {cluster}..." f"{TEXT_COLOR_DEFAULT}") def print_instances(): print( f"instances: " + str( [ f"{s.name}: {s.state.value}" + (f" on {s.provider_name}" if s.provider_id else "") for s in cluster.instances ] ) ) def still_starting(): return any( i.state in (ServiceState.pending, ServiceState.starting) for i in cluster.instances ) # wait until instances are started while still_starting() and datetime.now() < commissioning_time + STARTING_TIMEOUT: print_instances() await asyncio.sleep(5) if still_starting(): raise Exception(f"Failed to start instances before {STARTING_TIMEOUT} elapsed :( ...") print(f"{TEXT_COLOR_YELLOW}All instances started :){TEXT_COLOR_DEFAULT}") # allow the service to run for a short while # (and allowing its requestor-end handlers to interact with it) start_time = datetime.now() while datetime.now() < start_time + timedelta(seconds=running_time): print_instances() await asyncio.sleep(5) print(f"{TEXT_COLOR_YELLOW}Stopping {cluster}...{TEXT_COLOR_DEFAULT}") cluster.stop() # wait for instances to stop cnt = 0 while cnt < 10 and any(s.is_available for s in cluster.instances): print_instances() await asyncio.sleep(5) print_instances()
async def test_demand_resubscription(log_dir: Path, goth_config_path: Path, monkeypatch) -> None: """Test that checks that a demand is re-submitted after its previous submission expires.""" configure_logging(log_dir) # Override the default test configuration to create only one provider node nodes = [ { "name": "requestor", "type": "Requestor" }, { "name": "provider-1", "type": "VM-Wasm-Provider", "use-proxy": True }, ] goth_config = load_yaml(goth_config_path, [("nodes", nodes)]) vm_package = await vm.repo( image_hash="9a3b5d67b0b27746283cb5f287c13eab1beaa12d92a9f536b747c7ae", min_mem_gib=0.5, min_storage_gib=2.0, ) runner = Runner(base_log_dir=log_dir, compose_config=goth_config.compose_config) async with runner(goth_config.containers): requestor = runner.get_probes(probe_type=RequestorProbe)[0] env = dict(os.environ) env.update(requestor.get_agent_env_vars()) # Setup the environment for the requestor for key, val in env.items(): monkeypatch.setenv(key, val) monitor = EventMonitor() monitor.add_assertion(assert_demand_resubscribed) monitor.start() # The requestor enable_default_logger() async def worker(work_ctx, tasks): async for task in tasks: script = work_ctx.new_script() script.run("/bin/sleep", "5") yield script task.accept_result() async with Golem( budget=10.0, event_consumer=monitor.add_event_sync, ) as golem: task: Task # mypy needs this for some reason async for task in golem.execute_tasks( worker, [Task(data=n) for n in range(20)], vm_package, max_workers=1, timeout=timedelta(seconds=30), ): logger.info("Task %d computed", task.data) await monitor.stop() for a in monitor.failed: raise a.result()