I have a web scraper which uses rust-bert library for NLP and tokio. I've tried to add #[tokio::main] on top of scrape_article and to add it to main.rs into tokio::task::spawn_blocking but no results I'm getting this error
Finished dev [unoptimized + debuginfo] target(s) in 14.41s
Running `target/debug/stock-perception-api`
[2022-08-23T13:57:14Z INFO stock_perception_api::config::db] Configuring Database...
thread 'main' panicked at 'Cannot drop a runtime in a context where blocking is not allowed. This happens when a runtime is dropped from within an asynchronous context.', /home/r/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.20.1/src/runtime/blocking/shutdown.rs:51:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fish: Job 1, 'cargo run' terminated by signal SIGSEGV (Address boundary error)
Here is the function which gives the error, more precisely the function get_sentiment
pub async fn scrape_article(conn: &Pool) {
let stocks_repo = StockRepo::new(conn);
let sentiment_repo = SentimentRepo::new(conn);
let article_repo = ArticleRepo::new(conn);
let count = get_count_of_stocks(stocks_repo).unwrap();
for item in 1..=count {
let links = get_all_article_links_by_stock_id(article_repo, item as i32).unwrap();
for link in links {
let parsing_result = parse_article(&link).await.unwrap();
let sentiment: Vec<Sentiment> = get_sentiment(&parsing_result.content).await.unwrap(); ------> Err
let new_sentiment;
if sentiment[0].polarity == SentimentPolarity::Negative {
new_sentiment = SentimentDTO::new(false, sentiment[0].score);
} else {
new_sentiment = SentimentDTO::new(true, sentiment[0].score);
}
create_sentiment(sentiment_repo, new_sentiment).unwrap();
}
}
()
}
get_sentiment function
pub async fn get_sentiment(
article_content: &str,
) -> Result<Vec<Sentiment>, Box<dyn std::error::Error>> {
let sentiment_classifier: SentimentModel = SentimentModel::new(Default::default())?;
let input: [&str; 1] = [article_content];
let output: Vec<Sentiment> = sentiment_classifier.predict(&input);
println!("{:?}", output[0]);
Ok(output)
}
main.rs
#[tokio::main]
async fn main() -> io::Result<()> {
dotenv().ok();
env_logger::init_from_env(Env::default().default_filter_or("info"));
let app_host = env::var(constants::APP_HOST).expect("APP_HOST not found.");
let app_port = env::var(constants::APP_PORT).expect("APP_PORT not found.");
let app_url = format!("{}:{}", &app_host, &app_port);
let db_url = env::var(constants::DATABASE_URL).expect("DATABASE_URL not found.");
let pool = config::db::migrate_and_config_db(&db_url);
scrape_article(&pool).await;
HttpServer::new(move || {
App::new()
.wrap(Cors::permissive())
.app_data(web::Data::new(pool.clone()))
.wrap(Logger::default())
.wrap(Logger::new("%a %s %{User-Agent}i"))
.configure(config::app::config_services)
})
.bind(app_url)?
.run()
.await
}
I've fixed it by using the async example of the NLP library.