지난번에 synchronous 버전으로 삽질하다가 실패해서 asynchronous 버전인 tokio-postgres 로 다시 도전 했다.
우선 crate를 바꾸자.
...
[dependencies]
rocket = "0.5.0-rc.2"
tokio-postgres = "0.7.7"
main.rs에 샘플을 복붙하자.
#[macro_use] extern crate rocket;
extern crate tokio_postgres;
use tokio_postgres::{NoTls};
async fn test_db() -> Result<(), tokio_postgres::Error> {
let (client, connection) = tokio_postgres::connect("host=localhost user=postgres password=hello1234$#@! dbname=portfolio_test", NoTls).await?;
let ret = client.query("SELECT id, name FROM tb_user;", &[]).await?;
for row in ret {
let id: i32 = row.get(0);
let name: &str = row.get(1);
println!("found user: {} {}", id, name);
}
return Ok(())
}
#[get("/")]
async fn index() -> &'static str {
test_db().await;
return "Hello, world!"
}
전반적으로 샘플에 있는 tokio_postgres 로 변경하고, await 를 붙여서 비동기로 결과를 받게 했다.
거기에 샘플 코드를 보다 보니 리턴 타입으로 Result<(), tokio_postgres::Error> 으로 써서 좀 더 깔끔하게 ? 로 처리가 가능했다. (이전에는 .ok()? 로 처리)
ok 를 붙이는 건 rust 컴파일러가 알려주었는데 이걸 알려줬어야지.
cargo run 을 다시 해 보자.
그런데 빌드는 잘 된것 같은데, 해당 url 을 열면 응답이 오지 않는다.
=_=
체크를 하다보니 요 라인에서 응답이 오지 않는다.
let ret = client.query("SELECT id, name FROM tb_user;", &[]).await?;
샘플 코드를 보다 보니 빼먹은게 있었다. 뭔가 자동으로 생성 될 줄 알았는데, 명시적으로 async task 를 만들어 줘야 하나보다.
tokio 를 추가하고 async task 를 스폰해서 커넥션을 맺어주자.
...
[dependencies]
tokio = "1.0"
rocket = "0.5.0-rc.2"
tokio-postgres = "0.7.7"
#[macro_use] extern crate rocket;
extern crate tokio_postgres;
extern crate tokio;
use tokio_postgres::{NoTls};
async fn test_db() -> Result<(), tokio_postgres::Error> {
let (client, connection) = tokio_postgres::connect("host=localhost user=postgres password=hello1234$#@! dbname=portfolio_test", NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
실행 해 보니 잘 된다.
🚀 Rocket has launched from http://127.0.0.1:8000
GET / text/html:
>> Matched: (index) GET /
found user: 1 galaxy
>> Outcome: Success
>> Response succeeded.
간단하게 샘플을 복붙해서 만들었는데 살펴볼께 많이 생겼다.