or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actors.mdbuilds.mdindex.mdlogging.mdrequest-queues.mdruns.mdschedules.mdstorage.mdstore.mdtasks.mdusers.mdwebhooks.md

runs.mddocs/

0

# Run Management

1

2

Actor run lifecycle management including execution monitoring, result access, and advanced operations like metamorphosis, resurrection, and real-time status tracking.

3

4

## Capabilities

5

6

### Run Operations

7

8

Individual run management with comprehensive lifecycle control and monitoring capabilities.

9

10

```python { .api }

11

class RunClient:

12

def get(self) -> dict | None:

13

"""Get run information including status, statistics, and metadata."""

14

15

def update(

16

self,

17

*,

18

status_message: str | None = None,

19

is_status_message_terminal: bool | None = None,

20

general_access: RunGeneralAccess | None = None

21

) -> dict:

22

"""Update run configuration.

23

24

Args:

25

status_message: Custom status message

26

is_status_message_terminal: Whether status message is final

27

general_access: Run access level (from apify_shared.consts)

28

"""

29

30

def delete(self) -> None:

31

"""Delete run and its associated data."""

32

33

def abort(self, *, gracefully: bool | None = None) -> dict:

34

"""Abort running Actor run.

35

36

Args:

37

gracefully: Whether to allow graceful shutdown

38

"""

39

40

def wait_for_finish(self, *, wait_secs: int | None = None) -> dict | None:

41

"""Wait for run completion.

42

43

Args:

44

wait_secs: Maximum wait time in seconds

45

"""

46

47

def metamorph(self, *, target_actor_id: str, **kwargs) -> dict:

48

"""Transform run into different Actor.

49

50

Args:

51

target_actor_id: ID of target Actor

52

build: Target build ID

53

content_type: Input content type

54

**kwargs: Additional metamorphosis parameters

55

"""

56

57

def resurrect(self, **kwargs) -> dict:

58

"""Resurrect finished run with same configuration.

59

60

Args:

61

build: Build ID to use

62

memory: Memory allocation

63

timeout: Run timeout

64

**kwargs: Additional run parameters

65

"""

66

67

def reboot(self) -> dict:

68

"""Reboot running Actor run."""

69

70

def dataset(self) -> DatasetClient:

71

"""Get default dataset client for this run."""

72

73

def key_value_store(self) -> KeyValueStoreClient:

74

"""Get default key-value store client for this run."""

75

76

def request_queue(self) -> RequestQueueClient:

77

"""Get default request queue client for this run."""

78

79

def log(self) -> LogClient:

80

"""Get log client for this run."""

81

82

def get_streamed_log(self, **kwargs) -> StreamedLog:

83

"""Get streamed log instance for real-time log monitoring.

84

85

Args:

86

**kwargs: Streaming configuration parameters

87

"""

88

89

def charge(self, event_name: str, **kwargs) -> None:

90

"""Charge for pay-per-event run.

91

92

Args:

93

event_name: Name of billable event

94

**kwargs: Event parameters

95

"""

96

97

def get_status_message_watcher(self, **kwargs) -> StatusMessageWatcher:

98

"""Get status message watcher for real-time status updates.

99

100

Args:

101

**kwargs: Watcher configuration parameters

102

"""

103

104

class RunClientAsync:

105

"""Async version of RunClient with identical methods."""

106

107

class RunCollectionClient:

108

def list(

109

self,

110

*,

111

limit: int | None = None,

112

offset: int | None = None,

113

desc: bool | None = None,

114

status: str | None = None

115

) -> ListPage[dict]:

116

"""List Actor runs.

117

118

Args:

119

limit: Maximum number of runs

120

offset: Pagination offset

121

desc: Sort in descending order

122

status: Filter by run status

123

"""

124

125

class RunCollectionClientAsync:

126

"""Async version of RunCollectionClient with identical methods."""

127

```

128

129

### Real-time Monitoring Types

130

131

```python { .api }

132

class StreamedLog:

133

"""Real-time log streaming interface."""

134

135

def __iter__(self) -> Iterator[str]:

136

"""Iterate over log lines in real-time."""

137

138

def close(self) -> None:

139

"""Close log stream."""

140

141

class StatusMessageWatcher:

142

"""Real-time status message monitoring interface."""

143

144

def __iter__(self) -> Iterator[dict]:

145

"""Iterate over status message updates."""

146

147

def close(self) -> None:

148

"""Close status watcher."""

149

```

150

151

## Usage Examples

152

153

### Basic Run Management

154

155

```python

156

from apify_client import ApifyClient

157

158

client = ApifyClient('your-api-token')

159

160

# Start Actor and get run

161

actor = client.actor('john-doe/web-scraper')

162

run = actor.start(run_input={'startUrls': ['https://example.com']})

163

164

# Monitor run progress

165

run_client = client.run(run['id'])

166

run_info = run_client.get()

167

168

print(f"Run status: {run_info['status']}")

169

print(f"Started at: {run_info['startedAt']}")

170

171

# Wait for completion

172

final_run = run_client.wait_for_finish(wait_secs=300)

173

if final_run:

174

print(f"Run finished with status: {final_run['status']}")

175

print(f"Usage: {final_run['stats']}")

176

else:

177

print("Run timeout reached")

178

```

179

180

### Advanced Run Operations

181

182

```python

183

# Metamorphosis - transform running Actor into different Actor

184

run_client = client.run('current-run-id')

185

186

# Transform to data processing Actor

187

new_run = run_client.metamorph(

188

target_actor_id='data-processor/clean-data',

189

run_input={'source': 'transformed_data'}

190

)

191

192

print(f"Metamorphosed to new run: {new_run['id']}")

193

194

# Resurrect failed run

195

failed_run = client.run('failed-run-id')

196

resurrected = failed_run.resurrect(

197

memory=4096, # Increase memory

198

timeout=7200 # Increase timeout

199

)

200

201

print(f"Resurrected run: {resurrected['id']}")

202

```

203

204

### Real-time Monitoring

205

206

```python

207

import time

208

from datetime import datetime

209

210

# Real-time log monitoring

211

run_client = client.run('active-run-id')

212

213

# Stream logs in real-time

214

with run_client.get_streamed_log() as log_stream:

215

for log_line in log_stream:

216

timestamp = datetime.now().strftime('%H:%M:%S')

217

print(f"[{timestamp}] {log_line.strip()}")

218

219

# Break on certain conditions

220

if 'ERROR' in log_line:

221

print("Error detected, investigating...")

222

break

223

224

# Monitor status messages

225

with run_client.get_status_message_watcher() as status_watcher:

226

for status_update in status_watcher:

227

print(f"Status: {status_update['status']}")

228

print(f"Message: {status_update.get('statusMessage', 'No message')}")

229

230

if status_update['status'] in ['SUCCEEDED', 'FAILED', 'ABORTED']:

231

break

232

```

233

234

### Data Access and Processing

235

236

```python

237

# Access run's default storage

238

run_client = client.run('completed-run-id')

239

240

# Get results from default dataset

241

dataset = run_client.dataset()

242

items = dataset.list_items()

243

244

print(f"Run produced {items.count} items")

245

246

# Process results

247

for item in items.items:

248

# Process each scraped item

249

process_scraped_data(item)

250

251

# Access metadata from key-value store

252

kvs = run_client.key_value_store()

253

input_data = kvs.get_record('INPUT')

254

output_data = kvs.get_record('OUTPUT')

255

256

print(f"Input: {input_data}")

257

print(f"Output: {output_data}")

258

259

# Get screenshot if available

260

screenshot = kvs.get_record_as_bytes('SCREENSHOT')

261

if screenshot:

262

with open('run_screenshot.png', 'wb') as f:

263

f.write(screenshot)

264

```

265

266

### Run Analytics and Billing

267

268

```python

269

# Monitor multiple runs

270

runs = client.runs().list(limit=100)

271

272

total_compute_units = 0

273

total_data_transfer = 0

274

275

for run in runs.items:

276

run_client = client.run(run['id'])

277

run_details = run_client.get()

278

279

if run_details and run_details.get('stats'):

280

stats = run_details['stats']

281

total_compute_units += stats.get('computeUnits', 0)

282

total_data_transfer += stats.get('dataTransfer', 0)

283

284

print(f"Run {run['id']}: {stats.get('computeUnits', 0)} CU")

285

286

print(f"Total compute units: {total_compute_units}")

287

print(f"Total data transfer: {total_data_transfer} MB")

288

289

# Charge for pay-per-event run

290

pay_per_event_run = client.run('pay-per-event-run-id')

291

292

# Charge for custom events

293

pay_per_event_run.charge('api_call', count=150)

294

pay_per_event_run.charge('data_extraction', items=500)

295

pay_per_event_run.charge('image_processing', images=25)

296

```

297

298

### Error Handling and Recovery

299

300

```python

301

# Graceful run management with error handling

302

def manage_run_lifecycle(actor_id, run_input):

303

client = ApifyClient('your-api-token')

304

305

try:

306

# Start run

307

run = client.actor(actor_id).start(run_input=run_input)

308

run_client = client.run(run['id'])

309

310

# Monitor with timeout

311

result = run_client.wait_for_finish(wait_secs=1800) # 30 minutes

312

313

if not result:

314

# Timeout reached, abort gracefully

315

print("Run timeout, aborting...")

316

run_client.abort(gracefully=True)

317

return None

318

319

if result['status'] == 'FAILED':

320

# Try resurrection with more resources

321

print("Run failed, attempting resurrection...")

322

resurrected = run_client.resurrect(

323

memory=8192,

324

timeout=3600

325

)

326

return resurrected

327

328

return result

329

330

except Exception as e:

331

print(f"Run management error: {e}")

332

# Clean up if needed

333

try:

334

run_client.abort()

335

except:

336

pass

337

return None

338

339

# Use the function

340

result = manage_run_lifecycle('my-actor', {'url': 'https://example.com'})

341

if result:

342

print(f"Run completed successfully: {result['id']}")

343

```