Skip to content

Commit

Permalink
Merge pull request #42 from lta-rs/backend_split
Browse files Browse the repository at this point in the history
Backend split
  • Loading branch information
zeon256 committed Mar 1, 2024
2 parents 796b882 + 56f21df commit d02ae23
Show file tree
Hide file tree
Showing 57 changed files with 1,911 additions and 1,517 deletions.
18 changes: 15 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,23 @@ jobs:
- uses: hecrj/setup-rust-action@v1
with:
rust-version: ${{ matrix.rust }}
- uses: actions/checkout@master
- name: Run tests
- uses: actions/checkout@v3
- name: Run tests (reqwest_async)
env:
API_KEY: ${{ secrets.API_KEY }}
run: cargo test --package lta --lib -- reqwest_async::tests
- name: Run tests (reqwest_blocking)
env:
API_KEY: ${{ secrets.API_KEY }}
run: cargo test --no-default-features --features reqwest-blocking --package lta --lib -- reqwest_blocking::tests
- name: Run tests (ureq_blocking)
env:
API_KEY: ${{ secrets.API_KEY }}
run: cargo test --no-default-features --features ureq-blocking --package lta --lib -- ureq_blocking::tests
- name: Build Examples
env:
API_KEY: ${{ secrets.API_KEY }}
run: cargo test --features blocking --verbose
run: cargo build --examples

rustdoc:
runs-on: ubuntu-latest
Expand Down
34 changes: 29 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "lta"
version = "0.6.0"
authors = ["budinverse <me@inve.rs>"]
edition = "2018"
edition = "2021"
homepage = "https://github.com/BudiNverse/lta-rs"
repository = "https://github.com/BudiNverse/lta-rs"
description = "🚍 Singapore LTA Datamall Rust Client written in pure rust with support for asynchronous requests"
Expand All @@ -20,16 +20,40 @@ exclude = [
name = "lta"

[features]
default = ["async-trait"]
blocking = ["reqwest/blocking"]
default = ["reqwest-async"]
reqwest-async = ["reqwest", "non-blocking-traits"]
reqwest-blocking = ["reqwest", "reqwest/blocking", "blocking-traits"]
fastfloat = ["lta_models/fastfloat"]
ureq-blocking = ["blocking-traits", "ureq"]
blocking-traits = []
non-blocking-traits = ["async-trait"]

[dependencies]
lta_models = { version = "0.4.0", default-features = false }
reqwest = { version = "0.11.10", features = ["json", "rustls"], default-features = false}
reqwest = { version = "0.11.10", features = ["json"], default-features = false, optional = true }
serde = { version = "1.0.137" }
async-trait = { version = "0.1.53", optional = true }
thiserror = "1.0.31"
ureq = { version = "2.5.0", features = ["json", "charset"], default-features = false, optional = true }
http = "0.2.8"

[dev-dependencies]
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"]}
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"]}

[[example]]
name = "bus_timing"
path = "examples/bus_timing.rs"

[[example]]
name = "reqwest_blocking"
path = "examples/reqwest_blocking.rs"
required-features = ["reqwest-blocking"]

[[example]]
name = "ureq"
path = "examples/ureq.rs"
required-features = ["ureq-blocking"]

[[example]]
name = "custom_client"
path = "examples/custom_client.rs"
6 changes: 3 additions & 3 deletions LIBDOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@
### API key setup
You can get your API key from [here](https://www.mytransport.sg/content/mytransport/home/dataMall/request-for-api.html)

```rust
use lta::{LTAResult, LTAClient, Client, Traffic, TrafficRequests};
```ignore
use lta::{LTAResult, LTAClient, Client, Traffic, TrafficRequests, reqwest_async::ReqwestAsync};
#[tokio::main]
async fn main() -> LTAResult<()> {
let api_key = std::env::var("API_KEY").expect("API_KEY not found!");
let client = LTAClient::with_api_key(api_key)?;
let client = LTAClient::<ReqwestAsync>::with_api_key(api_key)?;
let erp_rates = Traffic::get_erp_rates(&client, None).await?;
println!("{:?}", erp_rates);
Ok(())
Expand Down
132 changes: 49 additions & 83 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
### Cargo.toml setup
```toml
[dependencies]
# extra features available: blocking
lta = { version = "0.6.0" }
lta = { version = "0.7.0" }
```

### API key setup
Expand All @@ -50,89 +49,53 @@ async fn main() -> LTAResult<()> {
}
```

### Examples
<details>
<summary>
Getting bus timings
</summary>

```rust
use lta::{LTAResult, LTAClient, Client, Bus, BusRequests};
### Feature flags
| Feature | Description |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `default` (i.e no features added ) | Uses [`reqwest`](https://github.com/seanmonstar/reqwest) under the hood |
| `reqwest-blocking` | Uses [`reqwest::blocking`](https://github.com/seanmonstar/reqwest) under the hood |
| `ureq-blocking` | Uses [`ureq`](https://github.com/algesten/ureq) under the hood |
| `fastfloat` | Enables the [`fastfloat`](https://github.com/aldanor/fast-float-rust) impl for parsing floats (uses SIMD) |
| `non-blocking-traits` | Exports traits that can be use to impl non-blocking clients |
| `blocking-traits` | Exports traits that can be use to impl blocking clients |

### Feature flags examples
Using `ureq` only
```toml
[dependencies]
lta = { version = "0.7.0", default-features = false, features = ["ureq-blocking"]}
```

fn get_bus_arrival() -> LTAResult<()> {
let api_key = std::env::var("API_KEY").expect("API_KEY not found!");
let client = LTAClient::with_api_key(api_key);
let arrivals = Bus::get_arrival(&client, 83139, None)?;
println!("{:?}", arrivals);
Ok(())
}
Implementing another blocking backend
```toml
[dependencies]
lta = { version = "0.7.0", default-features = false, features = ["blocking-traits"]}
```

</details>

<details>
<summary>
Getting other data
</summary>

```rust
// All the APIs in this library are designed to be used like this
// `lta::RequestType::get_something`
// All of them return lta::utils::LTAResult<T>
// The example below is Bus::get_bus_services()
// and Traffic::get_erp_rates()
// Do note that the API calling convention is similar across all the APIs except for
// bus::get_arrival
// Most of the APIs returns only 500 record
// If you want to get records 501 - 1000 take a look at get_erp() example
use lta::{LTAResult, LTAClient, Client, Bus, Traffic, BusRequests, TrafficRequests};

async fn bus_services() -> LTAResult<()> {
let api_key = std::env::var("API_KEY").expect("API_KEY not found!");
let client = LTAClient::with_api_key(api_key)?;
let bus_services= Bus::get_bus_services(&client, None)?;
println!("{:?}", bus_services);
Ok(())
}

async fn get_erp() -> LTAResult<()> {
let api_key = std::env::var("API_KEY").expect("API_KEY not found!");
let client = LTAClient::with_api_key(api_key)?;
let erp_rates = Traffic::get_erp_rates(&client, 500)?;
println!("{:?}", erp_rates);
Ok(())
}
Implementing another async backend
```toml
[dependencies]
lta = { version = "0.7.0", default-features = false, features = ["non-blocking-traits"]}
```

</details>

### Custom Client
<details>
<summary>
There are some instances where you might need to customise the reqwest client due to certain limitations.
</summary>
### Backend Support
| Backend | Status | Github CI Run :octocat: |
| ---------------- | ----------- | ----------------------- |
| reqwest | Official ✔ | Yes ✔ ️ |
| reqwest blocking | Official ✔ ️ | Yes ✔️ |
| ureq | Official ✔ ️ | Yes ✔️ |
| surf | TBA ⭕ ️ | No ⭕ |

```rust
use lta::r#async::client::LTAClient;
use lta::reqwest::ClientBuilder;
use std::time::Duration;
use lta::Client;

fn my_custom_client() -> LTAClient {
let client = ClientBuilder::new()
.no_gzip()
.connect_timeout(Duration::new(420, 0))
.build()
.unwrap();

LTAClient::new("API_KEY", client)
}
```

</details>
### Examples
| Example | Description |
| ----------------------------------------------------- | ------------------------------------ |
| [bus_timing.rs](./examples/bus_timing.rs) | How to get bus timing (async used) |
| [reqwest_blocking.rs](./examples/reqwest_blocking.rs) | How to use reqwest blocking feature |
| [ureq_blocking.rs](./examples/ureq_blocking.rs) | How to use ureq backend |
| [custom_client.rs](./examples/custom_client.rs) | How to create custom backend clients |

### General advice
- Reuse `LTAClient` as it holds a connection pool internally
- Reuse `LTAClient<T>` as it holds a connection pool internally
- Reduce the number of times you call the API, take a look at `Update Freq` in the documentation and prevent
yourself from getting blacklisted. Use a caching mechanism.

Expand All @@ -147,14 +110,17 @@ yourself from getting blacklisted. Use a caching mechanism.

### Frequently Asked Questions

- Is this library being actively developed?
- Project is currently in maintenance mode. Won't really have any new features. Just bug fixes, minor upgrades etc.
Q: Is this library being actively developed?

A: Project is currently in maintenance mode. Won't really have any new features. Just bug fixes, minor upgrades etc.

Q: What are the APIs available?

A: All of the APIs are implemented. Take a look at the official LTA docs.

- What are the APIs available?
- All of the APIs are implemented. Take a look at the official LTA docs.
Q: Where do I get the official docs from lta?

- Where do I get the official docs from lta?
- You can get them [here](https://www.mytransport.sg/content/dam/datamall/datasets/LTA_DataMall_API_User_Guide.pdf)
A: You can get them [here](https://www.mytransport.sg/content/dam/datamall/datasets/LTA_DataMall_API_User_Guide.pdf)

### License
lta-rs is licensed under MIT license (LICENSE-MIT or <http://opensource.org/licenses/MIT>)
Expand Down
11 changes: 0 additions & 11 deletions example/Cargo.toml

This file was deleted.

7 changes: 0 additions & 7 deletions example/README.md

This file was deleted.

43 changes: 0 additions & 43 deletions example/src/main.rs

This file was deleted.

10 changes: 10 additions & 0 deletions examples/bus_timing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use lta::{LTAError, LTAClient, Client, Bus, BusRequests};

#[tokio::main]
async fn main() -> Result<(), LTAError> {
let api_key = env!("API_KEY");
let client = LTAClient::with_api_key(api_key)?;
let bus_timing = Bus::get_arrival(&client, 83139, None).await?;
dbg!(bus_timing);
Ok(())
}
18 changes: 18 additions & 0 deletions examples/custom_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use lta::{reqwest_async::ReqwestAsync, Bus, BusRequests, Client, LTAClient, LTAError};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), LTAError> {
let api_key = env!("API_KEY");

let custom_reqwest_client = ReqwestAsync::builder()
.connect_timeout(Duration::from_secs(10))
.no_brotli()
.build()
.map_err(|e| LTAError::BackendError(Box::new(e)))?;

let client = LTAClient::new(api_key, custom_reqwest_client);
let bus_timing = Bus::get_arrival(&client, 83139, None).await?;
dbg!(bus_timing);
Ok(())
}
13 changes: 13 additions & 0 deletions examples/reqwest_blocking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use lta::{
blocking::{prelude::TrafficRequests, LTAClient},
reqwest_blocking::ReqwestBlocking,
Client, LTAError, Traffic,
};

fn main() -> Result<(), LTAError> {
let api_key = env!("API_KEY");
let client = LTAClient::<ReqwestBlocking>::with_api_key(api_key)?;
let erp_rates = Traffic::get_erp_rates(&client, None)?;
dbg!(erp_rates);
Ok(())
}
13 changes: 13 additions & 0 deletions examples/ureq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use lta::{
blocking::{prelude::TrafficRequests, LTAClient},
ureq_blocking::Agent,
Client, LTAError, Traffic,
};

fn main() -> Result<(), LTAError> {
let api_key = env!("API_KEY");
let client = LTAClient::<Agent>::with_api_key(api_key)?;
let erp_rates = Traffic::get_carpark_avail(&client, None)?;
dbg!(erp_rates);
Ok(())
}
Loading

0 comments on commit d02ae23

Please sign in to comment.