# Getting Started with aioservicekit

This guide will walk you through the basics of `aioservicekit` and help you write your first asynchronous service.

## Installation

First, make sure you have `aioservicekit` installed:

```bash
pip install aioservicekit
```
*Note: If you are using Python < 3.11, `aioservicekit` might install `exceptiongroup` as a dependency for `TaskGroup` compatibility.*

## Your First Service

`aioservicekit` makes it easy to define services using decorators. Let's create a simple service that prints a message every second.

```python
import asyncio
import logging
from aioservicekit import service, run_services, main

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# Define the core logic of our service as an async function
async def my_worker(service_name: str):
    logging.info(f"Service '{service_name}' is doing work...")
    # In a real service, you might check queues, process data, etc.
    # Here we just sleep to simulate work.
    await asyncio.sleep(1)

# Use the @service decorator to turn the function into a service factory
@service(name="MySimpleService")
async def simple_service_worker():
    # This function will be called repeatedly by the service's __work__ loop
    await my_worker("MySimpleService")

@main # Ensures all background tasks complete before exit
async def app_main():
    logging.info("Application starting...")

    # Create an instance of our service
    my_service = simple_service_worker()

    # Use run_services to manage the lifecycle
    async with run_services([my_service]) as waiter:
        logging.info("Services are running. Press Ctrl+C to stop.")
        # waiter is an awaitable that completes when services stop naturally
        # (or are stopped externally). In this case, we rely on Ctrl+C.
        await waiter # Wait indefinitely until services stop

    logging.info("Application finished cleanly.")

if __name__ == "__main__":
    try:
        asyncio.run(app_main())
    except KeyboardInterrupt:
        logging.info("Shutdown requested by user.")
```

**Explanation:**

1.  **`my_worker`**: A regular `async` function containing the logic we want to run repeatedly.
2.  **`@service(name="MySimpleService")`**: This decorator wraps `simple_service_worker`. When `simple_service_worker()` is called, it doesn't run the function directly but returns a `Service` instance (`FnService` internally).
3.  **`simple_service_worker`**: This function *defines* the work loop. It will be called repeatedly by the `Service` generated by the decorator.
4.  **`@main`**: This decorator ensures that if our service (or any other part of the application) spawned background `asyncio.Task`s, the application waits for them to finish before exiting completely after `app_main` returns.
5.  **`app_main`**: Our main application entry point.
6.  **`my_service = simple_service_worker()`**: We call the decorated function to get the actual `Service` instance.
7.  **`async with run_services([my_service]) as waiter:`**: This is the standard way to manage services.
    *   It automatically calls `my_service.start()` when entering the `with` block.
    *   It automatically calls `my_service.stop()` when exiting the `with` block (either normally or due to an exception like `KeyboardInterrupt`).
    *   It yields `waiter`, an awaitable that resolves when all managed services stop. We `await waiter` here to keep the application running until the service stops (e.g., by Ctrl+C, which triggers the `on_shutdown` event handled internally by the `Service`).
8.  **`asyncio.run(app_main())`**: Runs the main async function.
9.  **`KeyboardInterrupt` Handling**: Catches Ctrl+C to allow `run_services` to perform graceful shutdown.

Run this script, and you'll see the "Service 'MySimpleService' is doing work..." message printed every second until you press Ctrl+C.

## Next Steps

Now that you have a basic understanding, explore the other components:

*   Learn more about the [Service](./services.md) lifecycle and defining services using classes.
*   Create [Periodic Tasks](./tasks.md) that run on a schedule.
*   Use [Channels](./channels.md) for communication.
*   Leverage the [Event System](./events.md).
*   Manage tasks with [Task Groups](./task_groups.md).
*   Understand the [Utilities](./utils.md) like `run_services` and `main` in more detail.
