|
1 | 1 | use serde::{Deserialize, Serialize}; |
| 2 | +use std::iter; |
2 | 3 | use tokio::fs; |
3 | 4 | use twilight_gateway::{Config, ConfigBuilder, Session, Shard, ShardId}; |
4 | 5 |
|
@@ -54,37 +55,37 @@ pub async fn save(info: &[Info]) -> anyhow::Result<()> { |
54 | 55 | } |
55 | 56 |
|
56 | 57 | /// Restores shard resumption information from the file system. |
57 | | -pub async fn restore(config: Config, shards: u32) -> Vec<Shard> { |
| 58 | +pub async fn restore(config: Config, recommended_shards: u32) -> Vec<Shard> { |
58 | 59 | let info = async { |
59 | 60 | let contents = fs::read(INFO_FILE).await?; |
60 | 61 | Ok::<_, anyhow::Error>(serde_json::from_slice::<Vec<Info>>(&contents)?) |
61 | 62 | } |
62 | 63 | .await; |
63 | 64 |
|
64 | | - let shard_ids = (0..shards).map(|shard| ShardId::new(shard, shards)); |
65 | | - |
66 | | - // A session may only be successfully resumed if it retains its shard ID, but |
67 | | - // Discord may have recommend a different shard count (producing different shard |
68 | | - // IDs). |
69 | | - let shards: Vec<_> = if let Ok(info) = info |
70 | | - && info.len() == shards as usize |
| 65 | + // The recommended shard count targets 1000 guilds per shard (out of a maximum |
| 66 | + // of 2500), so it might be different from the previous shard count. |
| 67 | + let shards = if let Ok(info) = info |
| 68 | + && recommended_shards / 2 <= info.len() as u32 |
71 | 69 | { |
72 | 70 | tracing::info!("resuming previous gateway sessions"); |
73 | | - shard_ids |
| 71 | + let configs = iter::repeat_n(config, info.len()) |
74 | 72 | .zip(info) |
75 | | - .map(|(shard_id, info)| { |
76 | | - let builder = ConfigBuilder::from(config.clone()).resume_info(info); |
77 | | - Shard::with_config(shard_id, builder.build()) |
78 | | - }) |
79 | | - .collect() |
| 73 | + .map(|(config, info)| ConfigBuilder::from(config).resume_info(info).build()); |
| 74 | + shards(configs).collect() |
80 | 75 | } else { |
81 | | - shard_ids |
82 | | - .map(|shard_id| Shard::with_config(shard_id, config.clone())) |
83 | | - .collect() |
| 76 | + shards(iter::repeat_n(config, recommended_shards as usize)).collect() |
84 | 77 | }; |
85 | 78 |
|
86 | 79 | // Resumed or not, the saved resume info is now stale. |
87 | 80 | _ = fs::remove_file(INFO_FILE).await; |
88 | 81 |
|
89 | 82 | shards |
90 | 83 | } |
| 84 | + |
| 85 | +fn shards(configs: impl ExactSizeIterator<Item = Config>) -> impl ExactSizeIterator<Item = Shard> { |
| 86 | + let total = configs.len().try_into().unwrap(); |
| 87 | + (0..total) |
| 88 | + .map(move |shard| ShardId::new(shard, total)) |
| 89 | + .zip(configs) |
| 90 | + .map(|(shard_id, config)| Shard::with_config(shard_id, config)) |
| 91 | +} |
0 commit comments