diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..6863fdd
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,10 @@
+Jenkinsfile
+LICENSE
+README.md
+.github
+.gitignore
+.idea
+.vscode
+Dockerfile
+docker-compose.yml
+.dockerignore
\ No newline at end of file
diff --git a/Todo.Api/appsettings.Development.json b/Todo.Api/appsettings.Development.json
index 8f3da45..a5052ea 100644
--- a/Todo.Api/appsettings.Development.json
+++ b/Todo.Api/appsettings.Development.json
@@ -1,6 +1,7 @@
{
"ConnectionStrings": {
- "SqliteConnection": "Data Source=Database/todo.db"
+ "SqliteConnection": "Data Source=Database/todo.db",
+ "RedisConnection": "localhost:6379"
},
"Logging": {
"LogLevel": {
diff --git a/Todo.Api/appsettings.json b/Todo.Api/appsettings.json
index 92e7429..8a59dad 100644
--- a/Todo.Api/appsettings.json
+++ b/Todo.Api/appsettings.json
@@ -1,7 +1,7 @@
{
"ConnectionStrings": {
"SqliteConnection": "Data Source=Database/todo.db",
- "SqlServerConnection": "Server=localhost,1433;Database=AuthDemo;User Id=sa;Password=23-7-2003@Mohamed;TrustServerCertificate=True;"
+ "RedisConnection": "localhost:6379"
},
"Logging": {
"LogLevel": {
diff --git a/Todo.Core/Interfaces/IRedisCacheService.cs b/Todo.Core/Interfaces/IRedisCacheService.cs
new file mode 100644
index 0000000..dc785aa
--- /dev/null
+++ b/Todo.Core/Interfaces/IRedisCacheService.cs
@@ -0,0 +1,66 @@
+namespace Todo.Core.Interfaces;
+
+///
+/// Interface for Redis Cache Service
+///
+public interface IRedisCacheService
+{
+ ///
+ /// Get data from Redis Cache
+ ///
+ ///
+ /// Key to get data from Redis Cache
+ ///
+ ///
+ /// Type of data to get from Redis Cache
+ ///
+ ///
+ /// Data from Redis Cache with the given key if exists, otherwise default value of the type
+ ///
+ Task GetData(string key);
+
+ ///
+ /// Set data in Redis Cache
+ ///
+ ///
+ /// Key to set data in Redis Cache
+ ///
+ ///
+ /// Data to set in Redis Cache
+ ///
+ ///
+ /// Type of data to set in Redis Cache
+ ///
+ ///
+ /// A task that represents the asynchronous operation
+ ///
+ Task SetData(string key, T data);
+
+ ///
+ /// Update data in Redis Cache
+ ///
+ ///
+ /// Key to update data in Redis Cache
+ ///
+ ///
+ /// Data to update in Redis Cache
+ ///
+ ///
+ /// Type of data to update in Redis Cache
+ ///
+ ///
+ /// A task that represents the asynchronous operation, containing the updated data
+ ///
+ Task UpdateData(string key, T data);
+
+ ///
+ /// Remove data from Redis Cache
+ ///
+ ///
+ /// Key to remove data from Redis Cache
+ ///
+ ///
+ /// A task that represents the asynchronous operation
+ ///
+ Task RemoveData(string key);
+}
\ No newline at end of file
diff --git a/Todo.Infrastructure/Configurations/Constants.cs b/Todo.Infrastructure/Configurations/Constants.cs
index c216019..bd1703a 100644
--- a/Todo.Infrastructure/Configurations/Constants.cs
+++ b/Todo.Infrastructure/Configurations/Constants.cs
@@ -3,6 +3,7 @@ namespace Todo.Infrastructure.Configurations;
public static class Constants
{
public const string ConnectionStringName = "SqliteConnection";
+ public const string RedisConnectionStringName = "RedisConnection";
public const string JwtConfigurationsSectionKey = "JwtConfigurations";
public const string AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@";
public const int TimeSpanByMinutesForCaching = 5;
diff --git a/Todo.Infrastructure/Extensions.cs b/Todo.Infrastructure/Extensions.cs
index f4872af..97f4abb 100644
--- a/Todo.Infrastructure/Extensions.cs
+++ b/Todo.Infrastructure/Extensions.cs
@@ -12,7 +12,8 @@
using Todo.Core.Interfaces;
using Todo.Infrastructure.Configurations;
using Todo.Infrastructure.DatabaseContexts;
-using Todo.Infrastructure.Repositories;
+using Todo.Infrastructure.Repositories.Cached;
+using Todo.Infrastructure.Repositories.DB;
using Todo.Infrastructure.Services;
using Task = Todo.Core.Entities.Task;
@@ -36,7 +37,12 @@ public static void RegisterRepositories(this WebApplicationBuilder builder)
public static void RegisterCachingRepositories(this WebApplicationBuilder builder)
{
- builder.Services.AddMemoryCache();
+ builder.Services.AddStackExchangeRedisCache(options =>
+ {
+ options.Configuration = builder.Configuration.GetConnectionString(Constants.RedisConnectionStringName);
+ options.InstanceName = "TodoFullStack_";
+ });
+ builder.Services.AddScoped();
builder.Services.AddScoped();
builder.Services.AddScoped, CachedListRepository>();
builder.Services.AddScoped, CachedTasksRepository>();
diff --git a/Todo.Infrastructure/Repositories/CachedAccountRepository.cs b/Todo.Infrastructure/Repositories/Cached/CachedAccountRepository.cs
similarity index 52%
rename from Todo.Infrastructure/Repositories/CachedAccountRepository.cs
rename to Todo.Infrastructure/Repositories/Cached/CachedAccountRepository.cs
index 9596e6d..6323f10 100644
--- a/Todo.Infrastructure/Repositories/CachedAccountRepository.cs
+++ b/Todo.Infrastructure/Repositories/Cached/CachedAccountRepository.cs
@@ -1,39 +1,39 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
-using Microsoft.Extensions.Caching.Memory;
using Todo.Core.DTOs.AccountDTOs;
using Todo.Core.Entities;
-using Todo.Core.Exceptions;
using Todo.Core.Interfaces;
-using Todo.Infrastructure.Configurations;
+using Todo.Infrastructure.Repositories.DB;
using Task = System.Threading.Tasks.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.Cached;
public class CachedAccountRepository : IAccountRepository
{
private readonly AccountRepository _accountRepository;
- private readonly IMemoryCache _memoryCache;
+ private readonly IRedisCacheService _cacheService;
- public CachedAccountRepository(AccountRepository accountRepository, IMemoryCache memoryCache)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public CachedAccountRepository(AccountRepository accountRepository, IRedisCacheService cacheService)
{
_accountRepository = accountRepository;
- _memoryCache = memoryCache;
+ _cacheService = cacheService;
}
public async Task GetUserById(string userId)
{
var cacheKey = $"User-{userId}";
- var cachedUser = await _memoryCache.GetOrCreateAsync(
- cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching));
- return _accountRepository.GetUserById(userId);
- });
+ var cachedUser = await _cacheService.GetData(cacheKey);
+ if (cachedUser is not null) return cachedUser;
- return cachedUser ?? throw new UserNotFoundException($"User with id: {userId} not found");
+ var user = await _accountRepository.GetUserById(userId);
+ await _cacheService.SetData(cacheKey, user);
+ return user;
}
public async Task GetUserByClaims(ClaimsPrincipal claims)
@@ -46,25 +46,20 @@ public async Task GetUserByClaims(ClaimsPrincipal claims)
public async Task ChangePassword(ChangePasswordDto changePasswordDto)
{
await _accountRepository.ChangePassword(changePasswordDto);
-
- var cacheKey = $"User-{changePasswordDto.Id}";
- _memoryCache.Remove(cacheKey);
- _memoryCache.CreateEntry(cacheKey).Value = await _accountRepository.GetUserById(changePasswordDto.Id);
+ await _cacheService.UpdateData($"User-{changePasswordDto.Id}",
+ await _accountRepository.GetUserById(changePasswordDto.Id));
}
public async Task UpdateUserInfo(UpdateUserInfoDto updateUserInfoDto)
{
await _accountRepository.UpdateUserInfo(updateUserInfoDto);
-
- var cacheKey = $"User-{updateUserInfoDto.Id}";
- _memoryCache.Remove(cacheKey);
- _memoryCache.CreateEntry(cacheKey).Value = await _accountRepository.GetUserById(updateUserInfoDto.Id);
+ await _cacheService.UpdateData($"User-{updateUserInfoDto.Id}",
+ await _accountRepository.GetUserById(updateUserInfoDto.Id));
}
public async Task DeleteAccount(string id)
{
await _accountRepository.DeleteAccount(id);
- var cacheKey = $"User-{id}";
- _memoryCache.Remove(cacheKey);
+ await _cacheService.RemoveData($"User-{id}");
}
}
\ No newline at end of file
diff --git a/Todo.Infrastructure/Repositories/CachedListRepository.cs b/Todo.Infrastructure/Repositories/Cached/CachedListRepository.cs
similarity index 58%
rename from Todo.Infrastructure/Repositories/CachedListRepository.cs
rename to Todo.Infrastructure/Repositories/Cached/CachedListRepository.cs
index 7b1ff99..3c4e326 100644
--- a/Todo.Infrastructure/Repositories/CachedListRepository.cs
+++ b/Todo.Infrastructure/Repositories/Cached/CachedListRepository.cs
@@ -1,52 +1,50 @@
-using Microsoft.Extensions.Caching.Memory;
using Todo.Core.DTOs.ListDTOs;
using Todo.Core.Entities;
-using Todo.Core.Exceptions;
using Todo.Core.Interfaces;
-using Todo.Infrastructure.Configurations;
+using Todo.Infrastructure.Repositories.DB;
using Task = System.Threading.Tasks.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.Cached;
public class CachedListRepository : IRepository
{
private readonly ListRepository _listRepository;
- private readonly IMemoryCache _memoryCache;
-
- public CachedListRepository(ListRepository listRepository, IMemoryCache memoryCache)
+ private readonly IRedisCacheService _cacheService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public CachedListRepository(ListRepository listRepository, IRedisCacheService cacheService)
{
_listRepository = listRepository;
- _memoryCache = memoryCache;
+ _cacheService = cacheService;
}
public async Task> GetAllAsync(string id)
{
var cacheKey = $"User-{id}-Lists";
- var cachedLists = await _memoryCache.GetOrCreateAsync>(
- cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching));
- return _listRepository.GetAllAsync(id);
- });
+ var cachedLists = await _cacheService.GetData>(cacheKey);
+ if (cachedLists is not null) return cachedLists;
- return cachedLists ?? [];
+ var lists = await _listRepository.GetAllAsync(id);
+ var taskLists = lists.ToList();
+ await _cacheService.SetData(cacheKey, taskLists);
+ return taskLists;
}
public async Task GetByIdAsync(Guid id)
{
var cacheKey = $"List-{id}";
- var cachedList = await _memoryCache.GetOrCreateAsync(
- cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching));
- return _listRepository.GetByIdAsync(id);
- });
+ var cachedList = await _cacheService.GetData(cacheKey);
+ if (cachedList is not null) return cachedList;
- return cachedList ?? throw new ListNotFoundException($"The list with id: {id} was not found.");
+ var list = await _listRepository.GetByIdAsync(id);
+ await _cacheService.SetData(cacheKey, list);
+ return list;
}
public async Task AddAsync(AddListDto entity)
@@ -61,8 +59,7 @@ public async Task UpdateAsync(UpdateListDto entity)
var updatedList = await _listRepository.UpdateAsync(entity);
var cacheKey = $"List-{entity.Id}";
- _memoryCache.Remove(cacheKey);
- _memoryCache.CreateEntry(cacheKey).Value = updatedList;
+ await _cacheService.UpdateData(cacheKey, updatedList);
var list = await _listRepository.GetByIdAsync(entity.Id);
await UpdateAllListsInCache(list.UserId ?? throw new ArgumentNullException(list.UserId,
@@ -78,8 +75,7 @@ public async Task DeleteAsync(Guid id)
var list = await _listRepository.GetByIdAsync(id);
await _listRepository.DeleteAsync(id);
- _memoryCache.Remove($"List-{id}");
-
+ await _cacheService.RemoveData($"List-{id}");
await UpdateAllListsInCache(list.UserId ?? throw new ArgumentNullException(list.UserId,
"The list with the given id does not have a user id."));
}
@@ -87,7 +83,8 @@ public async Task DeleteAsync(Guid id)
private async Task UpdateAllListsInCache(string userId)
{
var cacheKey = $"User-{userId}-Lists";
- _memoryCache.Remove(cacheKey);
- _memoryCache.CreateEntry(cacheKey).Value = await _listRepository.GetAllAsync(userId);
+ var lists = await _listRepository.GetAllAsync(userId);
+ var taskLists = lists.ToList();
+ await _cacheService.UpdateData(cacheKey, taskLists);
}
}
\ No newline at end of file
diff --git a/Todo.Infrastructure/Repositories/CachedTasksRepository.cs b/Todo.Infrastructure/Repositories/Cached/CachedTasksRepository.cs
similarity index 58%
rename from Todo.Infrastructure/Repositories/CachedTasksRepository.cs
rename to Todo.Infrastructure/Repositories/Cached/CachedTasksRepository.cs
index eeb269b..4671a22 100644
--- a/Todo.Infrastructure/Repositories/CachedTasksRepository.cs
+++ b/Todo.Infrastructure/Repositories/Cached/CachedTasksRepository.cs
@@ -1,51 +1,49 @@
-using Microsoft.Extensions.Caching.Memory;
using Todo.Core.DTOs.TasksDtos;
-using Todo.Core.Exceptions;
using Todo.Core.Interfaces;
-using Todo.Infrastructure.Configurations;
+using Todo.Infrastructure.Repositories.DB;
using Task_Entity = Todo.Core.Entities.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.Cached;
public class CachedTasksRepository : IRepository
{
private readonly TasksRepository _tasksRepository;
- private readonly IMemoryCache _memoryCache;
+ private readonly IRedisCacheService _cacheService;
- public CachedTasksRepository(TasksRepository tasksRepository, IMemoryCache memoryCache)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public CachedTasksRepository(TasksRepository tasksRepository, IRedisCacheService cacheService)
{
_tasksRepository = tasksRepository;
- _memoryCache = memoryCache;
+ _cacheService = cacheService;
}
public async Task> GetAllAsync(string id)
{
var cacheKey = $"List-{id}-Tasks";
- var cachedTasks = await _memoryCache.GetOrCreateAsync>(
- cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching));
- return _tasksRepository.GetAllAsync(id);
- });
+ var cachedTasks = await _cacheService.GetData>(cacheKey);
+ if (cachedTasks is not null) return cachedTasks;
- return cachedTasks ?? [];
+ var tasks = await _tasksRepository.GetAllAsync(id);
+ var taskEntities = tasks.ToList();
+ await _cacheService.SetData(cacheKey, taskEntities);
+ return taskEntities;
}
public async Task GetByIdAsync(Guid id)
{
var cacheKey = $"Task-{id}";
- var cachedTask = await _memoryCache.GetOrCreateAsync(
- cacheKey,
- entry =>
- {
- entry.SetAbsoluteExpiration(TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching));
- return _tasksRepository.GetByIdAsync(id);
- });
+ var cachedTask = await _cacheService.GetData(cacheKey);
+ if (cachedTask is not null) return cachedTask;
- return cachedTask ?? throw new TaskNotFoundException($"The task with id: {id} was not found.");
+ var task = await _tasksRepository.GetByIdAsync(id);
+ await _cacheService.SetData(cacheKey, task);
+ return task;
}
public async Task AddAsync(AddTaskDto entity)
@@ -58,11 +56,9 @@ public async Task AddAsync(AddTaskDto entity)
public async Task UpdateAsync(UpdateTaskDto entity)
{
var updatedTask = await _tasksRepository.UpdateAsync(entity);
-
var taskEntity = await _tasksRepository.GetByIdAsync(entity.Id);
await UpdateAllTasksInCache(taskEntity.ListId.ToString() ??
throw new ArgumentNullException(taskEntity.ListId.ToString(), "The ListId cannot be null."));
-
return updatedTask;
}
@@ -72,9 +68,7 @@ public async Task DeleteAsync(Guid id)
{
var task = await GetByIdAsync(id);
await _tasksRepository.DeleteAsync(id);
-
- _memoryCache.Remove($"Task-{id}");
-
+ await _cacheService.RemoveData($"Task-{id}");
await UpdateAllTasksInCache(task.ListId.ToString() ??
throw new ArgumentNullException(task.ListId.ToString(), "The ListId cannot be null."));
}
@@ -82,7 +76,9 @@ await UpdateAllTasksInCache(task.ListId.ToString() ??
private async Task UpdateAllTasksInCache(string listId)
{
var cacheKey = $"List-{listId}-Tasks";
- _memoryCache.Remove(cacheKey);
- _memoryCache.CreateEntry(cacheKey).Value = await _tasksRepository.GetAllAsync(listId);
+ var task = await _tasksRepository.GetAllAsync(listId);
+ var taskEntities = task.ToList();
+ await _cacheService.RemoveData(cacheKey);
+ await _cacheService.SetData(cacheKey, taskEntities);
}
}
\ No newline at end of file
diff --git a/Todo.Infrastructure/Repositories/AccountRepository.cs b/Todo.Infrastructure/Repositories/DB/AccountRepository.cs
similarity index 99%
rename from Todo.Infrastructure/Repositories/AccountRepository.cs
rename to Todo.Infrastructure/Repositories/DB/AccountRepository.cs
index 3a7e942..02aaf2a 100644
--- a/Todo.Infrastructure/Repositories/AccountRepository.cs
+++ b/Todo.Infrastructure/Repositories/DB/AccountRepository.cs
@@ -7,7 +7,7 @@
using Todo.Core.Interfaces;
using Task = System.Threading.Tasks.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.DB;
///
/// AccountService class is used to manage user operations like changing password, updating user information etc.
diff --git a/Todo.Infrastructure/Repositories/ListRepository.cs b/Todo.Infrastructure/Repositories/DB/ListRepository.cs
similarity index 99%
rename from Todo.Infrastructure/Repositories/ListRepository.cs
rename to Todo.Infrastructure/Repositories/DB/ListRepository.cs
index 6525d15..3c05c7d 100644
--- a/Todo.Infrastructure/Repositories/ListRepository.cs
+++ b/Todo.Infrastructure/Repositories/DB/ListRepository.cs
@@ -6,7 +6,7 @@
using Todo.Infrastructure.DatabaseContexts;
using Task = System.Threading.Tasks.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.DB;
///
/// A repository for managing the task lists.
diff --git a/Todo.Infrastructure/Repositories/RefreshTokenRepository.cs b/Todo.Infrastructure/Repositories/DB/RefreshTokenRepository.cs
similarity index 98%
rename from Todo.Infrastructure/Repositories/RefreshTokenRepository.cs
rename to Todo.Infrastructure/Repositories/DB/RefreshTokenRepository.cs
index af87671..46e1b8c 100644
--- a/Todo.Infrastructure/Repositories/RefreshTokenRepository.cs
+++ b/Todo.Infrastructure/Repositories/DB/RefreshTokenRepository.cs
@@ -5,7 +5,7 @@
using Todo.Infrastructure.DatabaseContexts;
using Task = System.Threading.Tasks.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.DB;
public class RefreshTokenRepository : IRefreshTokenRepository
{
diff --git a/Todo.Infrastructure/Repositories/TasksRepository.cs b/Todo.Infrastructure/Repositories/DB/TasksRepository.cs
similarity index 99%
rename from Todo.Infrastructure/Repositories/TasksRepository.cs
rename to Todo.Infrastructure/Repositories/DB/TasksRepository.cs
index 1a4121c..e543ec7 100644
--- a/Todo.Infrastructure/Repositories/TasksRepository.cs
+++ b/Todo.Infrastructure/Repositories/DB/TasksRepository.cs
@@ -5,7 +5,7 @@
using Todo.Infrastructure.DatabaseContexts;
using Task_Entity = Todo.Core.Entities.Task;
-namespace Todo.Infrastructure.Repositories;
+namespace Todo.Infrastructure.Repositories.DB;
///
/// A class that implements the IRepository interface for the Task entity.
diff --git a/Todo.Infrastructure/Services/RedisCachingService.cs b/Todo.Infrastructure/Services/RedisCachingService.cs
new file mode 100644
index 0000000..abf2994
--- /dev/null
+++ b/Todo.Infrastructure/Services/RedisCachingService.cs
@@ -0,0 +1,34 @@
+using System.Text.Json;
+using Microsoft.Extensions.Caching.Distributed;
+using Todo.Core.Interfaces;
+using Todo.Infrastructure.Configurations;
+
+namespace Todo.Infrastructure.Services;
+
+public class RedisCachingService(IDistributedCache cache) : IRedisCacheService
+{
+ public async Task GetData(string key)
+ {
+ var data = await cache.GetStringAsync(key);
+ return string.IsNullOrEmpty(data) ? default : JsonSerializer.Deserialize(data);
+ }
+
+ public async Task SetData(string key, T data)
+ {
+ var options = new DistributedCacheEntryOptions
+ {
+ AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching),
+ SlidingExpiration = TimeSpan.FromMinutes(Constants.TimeSpanByMinutesForCaching)
+ };
+ await cache.SetStringAsync(key, JsonSerializer.Serialize(data), options);
+ }
+
+ public async Task UpdateData(string key, T data)
+ {
+ await cache.RemoveAsync(key);
+ await SetData(key, data);
+ return data;
+ }
+
+ public async Task RemoveData(string key) => await cache.RemoveAsync(key);
+}
\ No newline at end of file
diff --git a/Todo.Infrastructure/Todo.Infrastructure.csproj b/Todo.Infrastructure/Todo.Infrastructure.csproj
index 1510193..ae0a4cb 100644
--- a/Todo.Infrastructure/Todo.Infrastructure.csproj
+++ b/Todo.Infrastructure/Todo.Infrastructure.csproj
@@ -19,7 +19,9 @@
+
+
diff --git a/Todo.sln b/Todo.sln
index 8fb644b..d249e65 100644
--- a/Todo.sln
+++ b/Todo.sln
@@ -8,6 +8,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{24FC08AC-E3BE-4FEC-9615-F92D133866B8}"
ProjectSection(SolutionItems) = preProject
docker-compose.yml = docker-compose.yml
+ Dockerfile = Dockerfile
+ Jenkinsfile = Jenkinsfile
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Todo.UnitTests", "Todo.UnitTests\Todo.UnitTests.csproj", "{08946D7C-7CEB-4C46-81C1-85AE850F72A7}"
diff --git a/docker-compose.yml b/docker-compose.yml
index 1f9dea5..fc6e496 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,4 +1,12 @@
services:
+ cache:
+ image: redis:alpine
+ container_name: todo-redis-cache
+ networks:
+ - todo-network
+ ports:
+ - "6379:6379"
+
api:
build: .
image: todo-api:latest
@@ -7,6 +15,8 @@ services:
- "8070:8080"
volumes:
- todo-db:/TodoApi/Database
+ networks:
+ - todo-network
environment:
- ASPNETCORE_ENVIRONMENT=Production
command:
@@ -14,4 +24,9 @@ services:
volumes:
todo-db:
- name: todo-db
\ No newline at end of file
+ name: todo-db
+
+networks:
+ todo-network:
+ driver: bridge
+ name: todo-network
\ No newline at end of file