Skip to content

Debug

In this section, you will learn how to debug container behavior in app-compose.

You will see how to:

  • Track the container startup process to understand what’s happening.
  • Identify why more or fewer containers started than expected.

This will help you quickly find and fix issues in your app.

Container Startup Process

const hireChef = () => ({
hasBreak: false,
makePizza: (_: { ingredients: string[] }) => 'pizza',
});
const orderIngredients = () => ['dough', 'sauce', 'cheese'];
const chef = createContainer({
id: 'John Doe',
domain: 'italian-chef',
start: async () => {
const hiredChef = await hireChef();
return { api: hiredChef };
},
});
const ingredients = createContainer({
id: 'ingredients',
domain: 'shop',
dependencies: [chef],
enable: (api) => api['John Doe'].hasBreak === false,
start: async () => {
const orderedIngredients = await orderIngredients();
return { api: { orderedIngredients } };
},
});
const pizza = createContainer({
id: 'pizza',
domain: 'dish',
dependencies: [chef, ingredients],
start: (api) => {
const pepperoniPizza = api['John Doe'].makePizza({
ingredients: api.ingredients.orderedIngredients,
});
return { api: { pizza: pepperoniPizza } };
},
});
const cmd = await compose({
stages: [
['prepare', [chef, ingredients]],
['cooking', [pizza]],
],
required: 'all',
});
await cmd.up({ debug: true });

When you run this code, you should see the following output in the console:

Terminal window
>> prepare
John Doe = idle
ingredients = idle
>> prepare
John Doe = pending
ingredients = idle
>> prepare
John Doe = done
ingredients = idle
>> prepare
John Doe = done
ingredients = pending
>> prepare
John Doe = done
ingredients = done
>> cooking
pizza = idle
>> cooking
pizza = pending
>> cooking
pizza = done

Try it

Understanding Why a Container Was Started or Skipped

For this, you can use the diff command, which shows which containers were started, skipped, or added automatically.

const hireChef = () => ({
hasBreak: false,
makePizza: (_: { ingredients: string[] }) => 'pizza',
});
const orderIngredients = () => ['dough', 'sauce', 'cheese'];
const chef = createContainer({
id: 'John Doe',
domain: 'italian-chef',
start: async () => {
const hiredChef = await hireChef();
return { api: hiredChef };
},
});
const ingredients = createContainer({
id: 'ingredients',
domain: 'shop',
dependencies: [chef],
enable: (api) => api['John Doe'].hasBreak === false,
start: async () => {
const orderedIngredients = await orderIngredients();
return { api: { orderedIngredients } };
},
});
const olives = createContainer({
id: 'olives',
domain: 'ingredients',
start: () => ({ api: { value: 'olives' } }),
});
const pizza = createContainer({
id: 'pizza',
domain: 'dish',
dependencies: [chef, ingredients],
optionalDependencies: [olives],
start: (api) => {
const pepperoniPizza = api['John Doe'].makePizza({
ingredients: api.ingredients.orderedIngredients,
});
return { api: { pizza: pepperoniPizza } };
},
});
const cmd = await compose({
stages: [
['prepare', [ingredients]],
['cooking', [pizza]],
],
required: 'all',
});
await cmd.diff();

When you run this code, you should see the following highlighted output in the console:

Terminal window
[app-compose] | diff command
All skipped containers are optional. If they are expected to work,
please include them in the list when calling `compose` function
Stages:
- prepare:
expected: [ ingredients ]
received: [ ingredients, John Doe ]
- cooking:
expected: [ pizza ]
received: [ pizza ]
skipped:
- olives: [pizza]

Try it