hvmd 0.1.0

productivity tool for those who need it the most
Documentation
pub mod avro;
pub mod nats;
pub mod process;
pub mod tasks;
use apache_avro::{Reader, Schema, from_value};
use async_nats::service::{self, ServiceExt};
use chrono::Local;
use clap::{ArgAction, arg, command, crate_authors};
use futures::{StreamExt, future::join};
use nats::get_client;
use process::TaskProcessor;
use tasks::{CreateTask, CreateTaskSerde, Model, Task};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
	let matches = command!()
		.author(crate_authors!("\n"))
		.subcommand_required(true)
		.subcommand(command!("start").about("starts up hivemind"))
		.subcommand(
			command!("tasks")
				.about("manage tasks")
				.subcommand_required(true)
				.subcommand(
					command!("create")
						.about("create a task")
						.arg(arg!(-t --title <TITLE> "tasks's title").required(true))
						.arg(arg!(-d --description [DESCRIPTION] "tasks's description"))
						.arg(
							arg!(-c --completed [COMPLETED] "if the task is completed or not (default: false)")
								.action(ArgAction::SetTrue),
						),
				),
		)
		.get_matches();

	let client = get_client().await?;
	match matches.subcommand() {
		Some(subcommand) => match subcommand {
			("start", _sub_matches) => {
				let processor = TaskProcessor::new(client);
				join(processor.process_tasks(), task_service()).await;
			}
			("tasks", sub_matches) => match sub_matches.subcommand() {
				Some(("create", sub_matches)) => {
					let title = sub_matches.get_one::<String>("title").unwrap().to_owned();
					let description = sub_matches
						.get_one::<String>("description")
						.map(|d| d.to_owned());
					let completed = sub_matches.get_flag("completed");

					let task = CreateTask {
						title,
						description,
						completed,
					};
					let encoded_task = CreateTaskSerde::serialize(task.clone())?;

					client.request("tasks.create", encoded_task).await?;

					println!("created task \"{}\"", task.title);
				}
				_ => unreachable!("subcommands were covered"),
			},
			_ => unreachable!("subcommands were covered"),
		},
		_ => unreachable!("or todo"),
	}

	Ok(())
}

async fn task_service() -> anyhow::Result<()> {
	let client = get_client().await?;
	let service = client
		.add_service(service::Config {
			name: "tasks".to_owned(),
			version: "0.1.0".to_owned(),
			description: None,
			stats_handler: None,
			metadata: None,
			queue_group: None,
		})
		.await
		.expect("should happen");
	let tasks_group = service.group("tasks");
	let mut endpoint = tasks_group.endpoint("create").await.expect("should happen");

	while let Some(request) = endpoint.next().await {
		let data = request.message.payload.clone();
		match CreateTaskSerde::deserialize(data) {
			Some(task) => {
				let serialized_task = CreateTaskSerde::serialize(task)?;
				client.publish("tasks", serialized_task).await?;
				request.respond(Ok("200".into())).await.unwrap();
			}
			None => request.respond(Ok("error".into())).await?,
		}
	}

	Ok(())
}