@@ -207,7 +207,7 @@ use super::payload::BookRequest;
207207use crate :: {errors :: Error , models :: Book , state :: AppState };
208208
209209pub async fn list (State (mut state ): State <AppState >) -> Result <impl IntoResponse , Error > {
210- let (limit , offset ) = (100 , 0 );
210+ let (limit , offset ) = (10 , 0 );
211211 let books =
212212 Book :: all (). limit (limit ). offset (offset ). exec (& mut state . db). await . map_err (| err | {
213213 error! (target : " database" , " failed to fetch: {err:?}" );
@@ -341,3 +341,95 @@ pub fn init(state: AppState) -> Router {
341341 . with_state (state )
342342}
343343```
344+
345+ ## Support Pagination
346+
347+ ### Add the Pagination
348+
349+ Add a new file ` book_service/src/app/shared/pagination.rs ` .
350+
351+ ``` rust
352+ use serde :: Deserialize ;
353+
354+ const DEFAULT_PER_PAGE : usize = 10 ;
355+ const MAX_PER_PAGE : usize = 100 ;
356+
357+ #[derive(Debug , Clone , Deserialize )]
358+ pub struct Pagination {
359+ #[serde(default = " default_per_page" )]
360+ pub per_page : usize ,
361+
362+ #[serde(default = " default_page" )]
363+ pub page : usize ,
364+ }
365+
366+ fn default_per_page () -> usize {
367+ DEFAULT_PER_PAGE
368+ }
369+
370+ fn default_page () -> usize {
371+ 1
372+ }
373+
374+ impl Pagination {
375+ pub fn limit_offset (self ) -> (usize , usize ) {
376+ let limit = self . per_page. clamp (1 , MAX_PER_PAGE );
377+ let page = std :: cmp :: max (1 , self . page);
378+ let offset = (page - 1 ) * limit ;
379+ (limit , offset )
380+ }
381+ }
382+ ```
383+
384+ Add ` book_service/src/app/shared/mod.rs ` .
385+
386+ ``` rust
387+ mod pagination ;
388+
389+ pub use pagination :: Pagination ;
390+ ```
391+
392+ Add ` pub mod shared; ` to ` book_service/src/app/mod.rs ` .
393+
394+ ### Attach it to Handler
395+
396+ Update ` book_service/src/app/book/handler.rs ` .
397+
398+ ``` rust
399+ use axum :: {
400+ Json ,
401+ extract :: {Path , Query , State },
402+ http :: StatusCode ,
403+ response :: IntoResponse ,
404+ };
405+ use tracing :: {error, info};
406+ use uuid :: Uuid ;
407+
408+ use super :: payload :: BookRequest ;
409+ use crate :: {app :: shared :: Pagination , errors :: Error , models :: Book , state :: AppState };
410+
411+ pub async fn list (
412+ State (mut state ): State <AppState >,
413+ Query (pagination ): Query <Pagination >,
414+ ) -> Result <impl IntoResponse , Error > {
415+ let (limit , offset ) = pagination . limit_offset ();
416+ let books =
417+ Book :: all (). limit (limit ). offset (offset ). exec (& mut state . db). await . map_err (| err | {
418+ error! (target : " database" , " failed to fetch: {err:?}" );
419+ Error :: DbFetch
420+ })? ;
421+ Ok ((StatusCode :: OK , Json (books )))
422+ }
423+ ```
424+
425+ ## Update justfile
426+
427+ Update ` book_service/justfile ` to add custom ` DB_HOST ` locally.
428+
429+ ``` justfile
430+ # Run server app
431+ app:
432+ @export $(grep -v '^#' .env | xargs) && \
433+ DB_HOST={{ db_host }} \
434+ cargo run --bin app
435+ ```
0 commit comments