# Custom Executor

Clique offers a wide range of tasks officially for various use cases. If these do not meet your requirements, you can create your own executors to cater to specific tasks seamlessly.

### Development Tools

To assist developers in quickly implementing a custom executor, Clique provides Rust [procedural macro](https://doc.rust-lang.org/reference/procedural-macros.html) support. Rust developers can directly use the procedural macros we provide to encapsulate the custom executor. Developers do not need to be concerned with how the executor interacts with the Clique network; they only need to focus on their own computational logic.

First, include the following dependencies in your Rust project:

```toml
clique-proc-macro = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
clique = { git = "https://github.com/CliqueOfficial/clique-protocol-sdk" }
```

Clique provides the following procedural macros:

* `#[namespace(name = ...)]`
  * The `namespace` macro ensures that all tasks within the annotated module are grouped under a specific namespace, and the namespace is corresbonding to the `name` in the Clique Task Manifest. For example, if the task's name is "clique\_httpsRequest," then the namespace should be specified as "clique."
* `#[task]`
  * The `task` macro is used to define a task struct. This macro annotates a struct that represents a task, allowing it to be recognized and managed by the task execution system.
  * You need to implement the `clique::Task` trait for the struct marked with the `task` macro, and within the `execute` method, implement your actual computational logic. Note that the input and output of the `execute` method are Rust struct generated based on the `input` and `output` section of your Clique Task Manifest file. You can directly use the field name from the manifest to access the corresbonding field in the input / output.
* `#[clique::async_trait]`
  * This macro is used to annotate the implementation of `clique::Task` trait, since this trait is `async`
* `#[executor(with(...))]`
  * The `executor` macro is used to define an executor struct that can handle the execution of multiple task modules. In the `with` field, fill in the name of the module decorated with the `namespace` macro. The tasks within these modules will be imported into your custom executor.

Here is an example:

```rust
use clique_proc_macro::{executor, namespace};

#[namespace(name = "yourOrganization")]
pub mod task_mod1 {
    #[task]
    pub struct HttpsRequest;

    #[clique::async_trait]
    impl clique::Task for HttpsRequest {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            let url = input.url;
            let encoding = input.encoding;

            for transformation in encoding.into_iter() {
                let json_ptr_str: String = transformation.from;
                let soltype_str: String = transformation.soltype;
                // ...
            }

            let response: Vec<u8> = // ...
            let output = HttpsRequestOutput { response };
            Ok(output)
        }
    }
    
    #[task]
    pub struct HttpsRequest2;

    #[clique::async_trait]
    impl clique::Task for HttpsRequest2 {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            // ...
        }
    }
}

#[namespace(name = "yourOrganization")]
pub mod task_mod2 {
    #[task]
    pub struct AnotherTask;

    #[clique::async_trait]
    impl clique::Task for AnotherTask {
        type Error = anyhow::Error;

        async fn execute(
            input: Self::Input,
        ) -> Result<Self::Output, Self::Error> {
            // ...
        }
    }
}

#[executor(with(
    task_mod1,
    task_mod2,
))]
pub struct MyCustomExecutor;
```
