itsi-scheduler 0.2.14 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +25 -82
  3. data/ext/itsi_scheduler/Cargo.toml +1 -1
  4. data/ext/itsi_scheduler/extconf.rb +3 -1
  5. data/ext/itsi_server/Cargo.lock +1 -1
  6. data/ext/itsi_server/Cargo.toml +3 -2
  7. data/ext/itsi_server/src/lib.rs +1 -0
  8. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +2 -2
  9. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +9 -11
  10. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +6 -1
  11. data/ext/itsi_server/src/server/binds/listener.rs +4 -1
  12. data/ext/itsi_server/src/server/http_message_types.rs +1 -1
  13. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +32 -34
  14. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +3 -4
  15. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +23 -38
  16. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +65 -14
  17. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +1 -1
  18. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +1 -1
  19. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +21 -8
  20. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +1 -5
  21. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +8 -6
  22. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +12 -3
  23. data/ext/itsi_server/src/server/process_worker.rs +2 -1
  24. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +96 -0
  25. data/ext/itsi_server/src/server/serve_strategy/mod.rs +1 -0
  26. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +80 -136
  27. data/ext/itsi_server/src/server/thread_worker.rs +10 -3
  28. data/ext/itsi_server/src/services/itsi_http_service.rs +26 -21
  29. data/ext/itsi_server/src/services/mime_types.rs +2893 -1413
  30. data/ext/itsi_server/src/services/rate_limiter.rs +16 -34
  31. data/ext/itsi_server/src/services/static_file_server.rs +147 -121
  32. data/ext/itsi_tracing/Cargo.toml +1 -1
  33. data/lib/itsi/schedule_refinement.rb +2 -2
  34. data/lib/itsi/scheduler/version.rb +1 -1
  35. metadata +3 -2
@@ -1,4 +1,5 @@
1
1
  use async_trait::async_trait;
2
+ use parking_lot::{Mutex, RwLock};
2
3
  use rand::Rng;
3
4
  use redis::aio::ConnectionManager;
4
5
  use redis::{Client, RedisError, Script};
@@ -6,9 +7,9 @@ use serde::Deserialize;
6
7
  use std::any::Any;
7
8
  use std::collections::{HashMap, HashSet};
8
9
  use std::result::Result;
9
- use std::sync::{Arc, LazyLock, Mutex};
10
+ use std::sync::{Arc, LazyLock};
10
11
  use std::time::{Duration, Instant};
11
- use tokio::sync::{Mutex as AsyncMutex, RwLock};
12
+ use tokio::sync::Mutex as AsyncMutex;
12
13
  use tokio::time::timeout;
13
14
  use tracing::warn;
14
15
  use url::Url;
@@ -242,10 +243,10 @@ impl InMemoryRateLimiter {
242
243
  /// Cleans up expired entries
243
244
  async fn cleanup(&self) {
244
245
  // Try to get the write lock, but fail open if we can't
245
- if let Ok(mut entries) = self.entries.try_write() {
246
- let now = Instant::now();
247
- entries.retain(|_, entry| entry.expires_at > now);
248
- }
246
+ let now = Instant::now();
247
+ self.entries
248
+ .write()
249
+ .retain(|_, entry| entry.expires_at > now);
249
250
  }
250
251
 
251
252
  /// Bans an IP address for the specified duration
@@ -258,12 +259,7 @@ impl InMemoryRateLimiter {
258
259
  let now = Instant::now();
259
260
  let ban_key = format!("ban:ip:{}", ip);
260
261
 
261
- let mut entries = self.entries.try_write().map_err(|e| {
262
- tracing::error!("Failed to acquire write lock: {}", e);
263
- RateLimitError::LockError
264
- })?;
265
-
266
- entries.insert(
262
+ self.entries.write().insert(
267
263
  ban_key,
268
264
  RateLimitEntry {
269
265
  count: 1, // Use count=1 to indicate banned
@@ -279,12 +275,7 @@ impl InMemoryRateLimiter {
279
275
  let now = Instant::now();
280
276
  let ban_key = format!("ban:ip:{}", ip);
281
277
 
282
- let entries = self.entries.try_read().map_err(|e| {
283
- tracing::error!("Failed to acquire read lock: {}", e);
284
- RateLimitError::LockError
285
- })?;
286
-
287
- if let Some(entry) = entries.get(&ban_key) {
278
+ if let Some(entry) = self.entries.read().get(&ban_key) {
288
279
  if entry.expires_at > now {
289
280
  // IP is banned, return a generic reason since we don't store reasons
290
281
  return Ok(Some("IP address banned".to_string()));
@@ -310,7 +301,7 @@ impl RateLimiter for InMemoryRateLimiter {
310
301
 
311
302
  let now = Instant::now();
312
303
 
313
- let mut entries = self.entries.write().await;
304
+ let mut entries = self.entries.write();
314
305
 
315
306
  let entry = entries
316
307
  .entry(key.to_string())
@@ -436,7 +427,7 @@ impl RateLimiterStore {
436
427
  ) -> Result<Arc<RedisRateLimiter>, RateLimitError> {
437
428
  // First check if this URL is known to fail
438
429
  {
439
- let failed_urls = self.failed_urls.lock().unwrap_or_else(|e| e.into_inner());
430
+ let failed_urls = self.failed_urls.lock();
440
431
  if failed_urls.contains(connection_url) {
441
432
  return Err(RateLimitError::ConnectionTimeout);
442
433
  }
@@ -444,10 +435,7 @@ impl RateLimiterStore {
444
435
 
445
436
  // Then check if we already have a limiter for this URL
446
437
  {
447
- let limiters = self
448
- .redis_limiters
449
- .lock()
450
- .unwrap_or_else(|e| e.into_inner());
438
+ let limiters = self.redis_limiters.lock();
451
439
  if let Some(limiter) = limiters.get(connection_url) {
452
440
  return Ok(limiter.clone());
453
441
  }
@@ -455,7 +443,7 @@ impl RateLimiterStore {
455
443
 
456
444
  // Get a dedicated mutex for this URL or create a new one if it doesn't exist
457
445
  let url_mutex = {
458
- let mut locks = CONNECTION_LOCKS.lock().unwrap_or_else(|e| e.into_inner());
446
+ let mut locks = CONNECTION_LOCKS.lock();
459
447
 
460
448
  // Get or create the mutex for this URL
461
449
  locks
@@ -476,10 +464,7 @@ impl RateLimiterStore {
476
464
 
477
465
  // Check again if another thread created the limiter while we were waiting
478
466
  {
479
- let limiters = self
480
- .redis_limiters
481
- .lock()
482
- .unwrap_or_else(|e| e.into_inner());
467
+ let limiters = self.redis_limiters.lock();
483
468
  if let Some(limiter) = limiters.get(connection_url) {
484
469
  return Ok(limiter.clone());
485
470
  }
@@ -492,10 +477,7 @@ impl RateLimiterStore {
492
477
  let limiter = Arc::new(limiter);
493
478
 
494
479
  // Store it for future use
495
- let mut limiters = self
496
- .redis_limiters
497
- .lock()
498
- .unwrap_or_else(|e| e.into_inner());
480
+ let mut limiters = self.redis_limiters.lock();
499
481
  limiters.insert(connection_url.to_string(), limiter.clone());
500
482
 
501
483
  Ok(limiter)
@@ -503,7 +485,7 @@ impl RateLimiterStore {
503
485
  Err(e) => {
504
486
  tracing::error!("Failed to initialize Redis rate limiter: {}", e);
505
487
  // Cache the failure
506
- let mut failed_urls = self.failed_urls.lock().unwrap_or_else(|e| e.into_inner());
488
+ let mut failed_urls = self.failed_urls.lock();
507
489
  failed_urls.insert(connection_url.to_string());
508
490
  Err(e)
509
491
  }