Metamorph
The metamorph operation transforms an Actor run into the run of another Actor with a new input.
This feature is useful if you want to use another Actor to finish the work of your current one instead of internally starting a new Actor run and waiting for it to finish. With metamorph, you can easily create new Actors on top of existing ones, and give your users a nicer input structure and user interface for the final Actor. The metamorph operation is completely transparent to the Actor's users; they will just see that your Actor got the work done.
Internally, the system stops the Docker container corresponding to the Actor run and starts a new container using a different Docker image. All the default storages are preserved, and the new input is stored under the INPUT-METAMORPH-1 key in the same default key-value store.
There is a limit on how many times you can metamorph a single run. You can check the limit in the Actor runtime limits.
To make your Actor compatible with the metamorph operation, use Actor.getInput()
instead of Actor.getValue('INPUT')
. This method will fetch the input using the right key INPUT-METAMORPH-1 in case of a metamorphed run.
For example, imagine you have an Actor that accepts a hotel URL on input and then internally uses the apify/web-scraper Actor to scrape all the hotel reviews. The metamorphing code would look like this:
- JavaScript
- Python
import { Actor } from 'apify';
await Actor.init();
// Get input of your Actor.
const { hotelUrl } = await Actor.getInput();
// Create input for apify/web-scraper
const newInput = {
startUrls: [{ url: hotelUrl }],
pageFunction: () => {
// Here you pass the page function that
// scrapes all the reviews ...
},
// ... and here would be all the additional
// input parameters.
};
// Transform the Actor run to apify/web-scraper
// with the new input.
await Actor.metamorph('apify/web-scraper', newInput);
// The line here will never be reached, because the
// Actor run will be interrupted.
await Actor.exit();
from apify import Actor
async def main():
async with Actor:
# Get input of your Actor
actor_input = await Actor.get_input() or {}
# Create input for apify/web-scraper
new_input = {
'startUrls': [{'url': actor_input['url']}],
'pageFunction': """
# Here you pass the page function that
# scrapes all the reviews ...
""",
# ... and here would be all the additional input parameters
}
# Transform the Actor run to apify/web-scraper with the new input
await Actor.metamorph('apify/web-scraper', new_input)
# The line here will never be reached, because the Actor run will be interrupted
Actor.log.info('This should not be printed')