88from dataclasses import dataclass
99from datetime import datetime
1010from functools import partial
11+ import time
1112from typing import List
1213
1314import aiohttp
1415import aiometer
1516from playwright .async_api import Browser , async_playwright
1617from yarl import URL
1718
19+ @dataclass
20+ class TimedResult [T ]:
21+ duration : float
22+ result : T
1823
1924@dataclass
2025class HubAccess :
@@ -43,8 +48,6 @@ class RunningServer(Server):
4348 Represents a running user server
4449 """
4550
46- start_request_time : datetime
47- start_completion_time : datetime
4851 server_url : URL
4952 startup_events : List [dict ]
5053
@@ -86,29 +89,30 @@ async def load_nbgitpuller_url(
8689 token : str ,
8790 nbgitpuller_url : NBGitpullerURL ,
8891 screenshot_name : str ,
89- ):
90- print (f"visiting { server .server_url } " )
91- start_time = datetime .now ()
92+ ) -> TimedResult [None ]:
93+ start_time = time .perf_counter ()
9294
9395 context = await browser .new_context (
9496 extra_http_headers = {"Authorization" : f"token { token } " }
9597 )
9698 page = await context .new_page ()
97- await page .goto (str (nbgitpuller_url .make_fullpath (server .server_url , secrets .token_hex (8 ))))
98- await page .wait_for_url (nbgitpuller_url .expected_final_url , timeout = 120 * 10 * 1000 )
99+ targetpath = secrets .token_hex (8 )
100+ going_to = nbgitpuller_url .make_fullpath (server .server_url , targetpath )
101+ await page .goto (str (going_to ))
102+ expected_final_full_url = str (nbgitpuller_url .make_expectedpath (server .server_url , targetpath ))
103+ await page .wait_for_url (expected_final_full_url , timeout = 120 * 10 * 1000 )
99104 await page .wait_for_load_state ("networkidle" )
100- await page .screenshot (path = screenshot_name )
101- duration = datetime .now () - start_time
102- print (f"{ server .server_url } completed test in { duration } " )
103-
105+ await page .screenshot (path = screenshot_name , timeout = 5 * 60 * 1000 )
106+ return TimedResult (time .perf_counter () - start_time , None )
104107
105108async def start_named_server (
106- session : aiohttp .ClientSession , server : Server , profile_options : dict [str , str ] | None = None
107- ) -> RunningServer | None :
109+ session : aiohttp .ClientSession , server : Server , profile_options : dict [str , str ] | None = None ,
110+ ) -> TimedResult [ RunningServer | None ] :
108111 """
109112 Try to start a named server as defined
110113
111114 """
115+ start_time = time .perf_counter ()
112116 headers = {"Authorization" : f"token { server .hub_access .token } " }
113117 server_api_url = (
114118 server .hub_access .url
@@ -119,12 +123,10 @@ async def start_named_server(
119123 )
120124 events = []
121125 async with session .post (server_api_url , headers = headers , json = profile_options ) as resp :
122- start_time = datetime .now ()
123126 if resp .status == 202 :
124127 # we are awaiting start, let's look for events
125- print (f"server { server .servername } waiting to start" )
126128 async with session .get (
127- server_api_url / "progress" , headers = headers
129+ server_api_url / "progress" , headers = headers , timeout = aiohttp . ClientTimeout ( 10 * 60 )
128130 ) as progress_resp :
129131 async for line in progress_resp .content :
130132 if line .decode ().strip () == "" :
@@ -133,17 +135,17 @@ async def start_named_server(
133135 progress_event = json .loads (line .decode ().strip ()[len ("data: " ) :])
134136 events .append (progress_event )
135137 if progress_event .get ("ready" ) == True :
136- print ( progress_event )
137- return RunningServer (
138- servername = server . servername ,
139- username = server .username ,
140- hub_access = server .hub_access ,
141- start_request_time = start_time ,
142- start_completion_time = datetime . now () ,
143- startup_events = events ,
144- server_url = URL (
145- server . hub_access . url / progress_event [ "url" ][ 1 :]
146- ), # Trim leading slashG
138+ return TimedResult (
139+ time . perf_counter () - start_time ,
140+ RunningServer (
141+ servername = server .servername ,
142+ username = server .username ,
143+ hub_access = server . hub_access ,
144+ startup_events = events ,
145+ server_url = URL (
146+ server . hub_access . url . joinpath ( progress_event [ "url" ]. lstrip ( "/" ), encoded = True )
147+ ),
148+ )
147149 )
148150 elif resp .status == 201 :
149151 # Means the server is immediately ready, and i don't want to deal with that yet
@@ -161,18 +163,29 @@ async def payload(
161163 profile_options : dict [str , str ] | None ,
162164 server : Server ,
163165):
164- started_server = await start_named_server (session , server , profile_options )
165- match started_server :
166- case RunningServer ():
167- await load_nbgitpuller_url (
168- browser ,
169- started_server ,
170- auth_token ,
171- nbgitpuller_url ,
172- server .servername + ".png" ,
173- )
174- case _:
175- print ("Server startup failed" )
166+ timing_info = {}
167+ print (f"Starting { server .servername } " )
168+ start_server_result = await start_named_server (session , server , profile_options )
169+ match start_server_result :
170+ case TimedResult (server_startup_duration , started_server ):
171+ timing_info ["server_startup" ] = server_startup_duration
172+ print (f"Started { server .servername } in { server_startup_duration :0.2f} s" )
173+ match started_server :
174+ case RunningServer ():
175+ print (f"Starting nbgitpuller for { server .servername } " )
176+ result = await load_nbgitpuller_url (
177+ browser ,
178+ started_server ,
179+ auth_token ,
180+ nbgitpuller_url ,
181+ server .servername + ".png" ,
182+ )
183+ timing_info ["nbgitpuller" ] = result .duration
184+ print (f"nbgitpuller completed for { server .servername } in { result .duration :0.2f} s" )
185+ case None :
186+ print ("Server startup failed" )
187+
188+ print (f"{ server .servername } : { timing_info } " )
176189
177190
178191async def main ():
@@ -181,10 +194,11 @@ async def main():
181194 argparser .add_argument ("server_prefix" , help = "Prefix used for named servers started in this run" )
182195 argparser .add_argument ("username" , help = "Name of the user" )
183196 argparser .add_argument ("servers_count" , type = int , help = "Number of servers to start" )
197+ # FIXME: This shouldn't be here.
184198 argparser .add_argument (
185199 "--max-concurrency" ,
186200 type = int ,
187- default = 30 ,
201+ default = 25 ,
188202 help = "Max Numbers of Servers to start at the same time" ,
189203 )
190204 argparser .add_argument (
0 commit comments