|
| 1 | +import Vapor |
| 2 | +import AlphaSwiftage |
| 3 | + |
| 4 | +struct AppContainer { |
| 5 | + // External services |
| 6 | + let alphavantage: AlphaVantageService |
| 7 | + |
| 8 | + // Mappers |
| 9 | + let currencyDTOMapper: CurrencyDTOMapper |
| 10 | + let tickerDTOMapper: TickerDTOMapper |
| 11 | + let loginResponseDTOMapper: LoginResponseDTOMapper |
| 12 | + let transactionDTOMapper: TransactionDTOMapper |
| 13 | + let portfolioDTOMapper: PortfolioDTOMapper |
| 14 | + let performanceDTOMapper: DatedPerformanceDTOMapper |
| 15 | + |
| 16 | + // Core repos/services |
| 17 | + let tickerRepository: PostgresTickerRepository |
| 18 | + let livePriceService: LivePriceService |
| 19 | + let quoteCache: PostgresQuoteRepository |
| 20 | + let priceService: CachedPriceService |
| 21 | + |
| 22 | + let userRepository: PostgresUserRepository |
| 23 | + let portfolioRepository: PostgresPortfolioRepository |
| 24 | + let transactionRepository: PostgresTransactionRepository |
| 25 | + let brokerageRepository: PostgresBrokerageRepository |
| 26 | + let brokerageAccountRepository: PostgresBrokerageAccountRepository |
| 27 | + let brokerageAccountDailyPerformanceRepository: PostgresBrokerageAccountDailyPerformanceRepository |
| 28 | + let brokerageDailyPerformanceRepository: PostgresBrokerageDailyPerformanceRepository |
| 29 | + |
| 30 | + let currencyRepository: PostgresCurrencyRepository |
| 31 | + |
| 32 | + // Calculators / updaters |
| 33 | + let performanceCalculator: HoldingsPerformanceCalculating |
| 34 | + let portfolioPerformanceUpdater: PortfolioPerformanceUpdater |
| 35 | + |
| 36 | + let portfolioService: PortfolioService |
| 37 | + let accountService: AccountService |
| 38 | + let brokerageService: BrokerageService |
| 39 | + let investmentService: InvestmentService |
| 40 | + let transactionService: TransactionService |
| 41 | + let tickersService: TickersService |
| 42 | + let brokerageAccountsService: BrokerageAccountsService |
| 43 | +} |
| 44 | + |
| 45 | +func buildAppContainer(_ app: Application) async throws -> AppContainer { |
| 46 | + let alphavantage = try await AlphaVantageService( |
| 47 | + serviceType: .rapidAPI(apiKey: app.config.alphavantageAPIKey()) |
| 48 | + ) |
| 49 | + |
| 50 | + let currencyDTOMapper = CurrencyDTOMapper() |
| 51 | + let tickerDTOMapper = TickerDTOMapper() |
| 52 | + let loginResponseDTOMapper = LoginResponseDTOMapper() |
| 53 | + |
| 54 | + let tickerRepository = PostgresTickerRepository(database: app.db) |
| 55 | + let livePriceService = LivePriceService(alphavantage: alphavantage) |
| 56 | + let quoteCache = PostgresQuoteRepository(database: app.db) |
| 57 | + let priceService = CachedPriceService(priceService: livePriceService, cache: quoteCache) |
| 58 | + |
| 59 | + let transactionDTOMapper = TransactionDTOMapper( |
| 60 | + currencyDTOMapper: currencyDTOMapper, |
| 61 | + database: app.db |
| 62 | + ) |
| 63 | + |
| 64 | + let investmentDTOMapper = InvestmentDTOMapper( |
| 65 | + currencyDTOMapper: currencyDTOMapper, |
| 66 | + transactionDTOMapper: transactionDTOMapper, |
| 67 | + tickerRepository: tickerRepository, |
| 68 | + priceService: priceService |
| 69 | + ) |
| 70 | + |
| 71 | + let userRepository = PostgresUserRepository(database: app.db) |
| 72 | + let portfolioRepository = PostgresPortfolioRepository(database: app.db) |
| 73 | + let transactionRepository = PostgresTransactionRepository(database: app.db) |
| 74 | + let brokerageRepository = PostgresBrokerageRepository(database: app.db) |
| 75 | + let brokerageAccountRepository = PostgresBrokerageAccountRepository(database: app.db) |
| 76 | + |
| 77 | + let brokerageAccountDailyPerformanceRepository = PostgresBrokerageAccountDailyPerformanceRepository(database: app.db) |
| 78 | + let brokerageDailyPerformanceRepository = PostgresBrokerageDailyPerformanceRepository(database: app.db) |
| 79 | + |
| 80 | + let performanceDTOMapper = DatedPerformanceDTOMapper() |
| 81 | + |
| 82 | + let portfolioDTOMapper = PortfolioDTOMapper( |
| 83 | + investmentDTOMapper: investmentDTOMapper, |
| 84 | + transactionDTOMapper: transactionDTOMapper, |
| 85 | + performanceDTOMapper: performanceDTOMapper, |
| 86 | + currencyDTOMapper: currencyDTOMapper |
| 87 | + ) |
| 88 | + |
| 89 | + let currencyRepository = PostgresCurrencyRepository(database: app.db) |
| 90 | + |
| 91 | + let performanceCalculator = HoldingsPerformanceCalculator(priceService: priceService) |
| 92 | + |
| 93 | + let portfolioPerformanceUpdater = PortfolioPerformanceUpdater( |
| 94 | + userRepository: userRepository, |
| 95 | + portfolioRepository: portfolioRepository, |
| 96 | + tickerRepository: PostgresTickerRepository(database: app.db), |
| 97 | + quoteCache: quoteCache, |
| 98 | + priceService: priceService, |
| 99 | + performanceCalculator: performanceCalculator, |
| 100 | + portfolioDailyRepo: PostgresPortfolioDailyPerformanceRepository(db: app.db) |
| 101 | + ) |
| 102 | + |
| 103 | + let portfolioService = PortfolioService(portfolioRepository: portfolioRepository, |
| 104 | + currencyRepository: currencyRepository, |
| 105 | + historicalPortfolioPerformanceUpdater: portfolioPerformanceUpdater, |
| 106 | + portfolioDailyRepo: PostgresPortfolioDailyPerformanceRepository(db: app.db), |
| 107 | + dataMapper: portfolioDTOMapper) |
| 108 | + |
| 109 | + let accountService = AccountService(userRepository: userRepository, userDataMapper: UserDTOMapper()) |
| 110 | + |
| 111 | + let brokerageService = BrokerageService( |
| 112 | + brokerageRepository: brokerageRepository, |
| 113 | + dtoMapper: BrokerageDTOMapper( |
| 114 | + brokerageRepository: brokerageRepository, |
| 115 | + accountDTOMapper: BrokerageAccountDTOMapper( |
| 116 | + brokerageAccountRepository: brokerageAccountRepository, |
| 117 | + currencyMapper: currencyDTOMapper, |
| 118 | + database: app.db |
| 119 | + ), |
| 120 | + performanceRepository: brokerageDailyPerformanceRepository, |
| 121 | + performanceDTOMapper: performanceDTOMapper, |
| 122 | + database: app.db |
| 123 | + ), |
| 124 | + accounts: brokerageAccountRepository, |
| 125 | + currencyMapper: currencyDTOMapper |
| 126 | + ) |
| 127 | + |
| 128 | + let investmentService = InvestmentService( |
| 129 | + portfolioRepository: portfolioRepository, |
| 130 | + dataMapper: InvestmentDTOMapper( |
| 131 | + currencyDTOMapper: currencyDTOMapper, |
| 132 | + transactionDTOMapper: transactionDTOMapper, |
| 133 | + tickerRepository: tickerRepository, |
| 134 | + priceService: priceService |
| 135 | + ) |
| 136 | + ) |
| 137 | + |
| 138 | + let transactionService = TransactionService(transactionsRepository: transactionRepository, |
| 139 | + currencyRepository: currencyRepository, |
| 140 | + dataMapper: transactionDTOMapper) |
| 141 | + |
| 142 | + let tickersService = TickersService( |
| 143 | + tickerRepository: tickerRepository, |
| 144 | + dataMapper: tickerDTOMapper, |
| 145 | + tickerService: alphavantage |
| 146 | + ) |
| 147 | + |
| 148 | + let tickerChangeHandler = TickerChangeHandler(priceService: priceService) |
| 149 | + tickersService.delegate = tickerChangeHandler |
| 150 | + |
| 151 | + let brokerageAccountsService = BrokerageAccountsService( |
| 152 | + brokerageRepository: brokerageRepository, |
| 153 | + brokerageAccountRepository: brokerageAccountRepository, |
| 154 | + performanceRepository: brokerageAccountDailyPerformanceRepository, |
| 155 | + performanceDTOMapper: performanceDTOMapper, |
| 156 | + currencyMapper: currencyDTOMapper, |
| 157 | + transactionDTOMapper: transactionDTOMapper, |
| 158 | + currencyRepository: currencyRepository |
| 159 | + ) |
| 160 | + |
| 161 | + |
| 162 | + return AppContainer( |
| 163 | + alphavantage: alphavantage, |
| 164 | + currencyDTOMapper: currencyDTOMapper, |
| 165 | + tickerDTOMapper: tickerDTOMapper, |
| 166 | + loginResponseDTOMapper: loginResponseDTOMapper, |
| 167 | + transactionDTOMapper: transactionDTOMapper, |
| 168 | + portfolioDTOMapper: portfolioDTOMapper, |
| 169 | + performanceDTOMapper: performanceDTOMapper, |
| 170 | + tickerRepository: tickerRepository, |
| 171 | + livePriceService: livePriceService, |
| 172 | + quoteCache: quoteCache, |
| 173 | + priceService: priceService, |
| 174 | + userRepository: userRepository, |
| 175 | + portfolioRepository: portfolioRepository, |
| 176 | + transactionRepository: transactionRepository, |
| 177 | + brokerageRepository: brokerageRepository, |
| 178 | + brokerageAccountRepository: brokerageAccountRepository, |
| 179 | + brokerageAccountDailyPerformanceRepository: brokerageAccountDailyPerformanceRepository, |
| 180 | + brokerageDailyPerformanceRepository: brokerageDailyPerformanceRepository, |
| 181 | + currencyRepository: currencyRepository, |
| 182 | + performanceCalculator: performanceCalculator, |
| 183 | + portfolioPerformanceUpdater: portfolioPerformanceUpdater, |
| 184 | + portfolioService: portfolioService, |
| 185 | + accountService: accountService, |
| 186 | + brokerageService: brokerageService, |
| 187 | + investmentService: investmentService, |
| 188 | + transactionService: transactionService, |
| 189 | + tickersService: tickersService, |
| 190 | + brokerageAccountsService: brokerageAccountsService |
| 191 | + ) |
| 192 | +} |
| 193 | + |
| 194 | +func installGlobalMiddleware(_ app: Application) { |
| 195 | + let globalRateLimiter = RateLimiterMiddleware(maxRequests: 100, perSeconds: 60) |
| 196 | + app.middleware.use(app.sessions.middleware) |
| 197 | + app.middleware.use(globalRateLimiter) |
| 198 | +} |
| 199 | + |
| 200 | +func scheduleNightlyJobs(_ app: Application, _ container: AppContainer) throws { |
| 201 | + if app.environment == .testing { return } |
| 202 | + |
| 203 | + let nightlyUpdaterJob = NightlyUpdaterJob( |
| 204 | + tickerPriceUpdater: TickerPriceUpdater( |
| 205 | + tickerRepository: container.tickerRepository, |
| 206 | + quoteCache: container.quoteCache, |
| 207 | + priceService: container.priceService |
| 208 | + ), |
| 209 | + portfolioPerformanceUpdater: container.portfolioPerformanceUpdater, |
| 210 | + brokerageAccountPerformanceUpdater: BrokerageAccountPerformanceUpdater( |
| 211 | + transactionRepository: container.transactionRepository, |
| 212 | + brokerageAccountRepository: container.brokerageAccountRepository, |
| 213 | + accountDailyRepository: container.brokerageAccountDailyPerformanceRepository, |
| 214 | + userRepository: container.userRepository, |
| 215 | + calculator: container.performanceCalculator |
| 216 | + ), |
| 217 | + brokeragePerformanceUpdater: BrokeragePerformanceUpdater( |
| 218 | + userRepository: container.userRepository, |
| 219 | + brokerageAccountRepository: container.brokerageAccountRepository, |
| 220 | + accountDailyRepository: container.brokerageAccountDailyPerformanceRepository, |
| 221 | + brokerageDailyRepository: container.brokerageDailyPerformanceRepository |
| 222 | + ) |
| 223 | + ) |
| 224 | + |
| 225 | + app.queues.schedule(nightlyUpdaterJob) |
| 226 | + .daily() |
| 227 | + .at(3, 0) |
| 228 | + |
| 229 | + app.queues.add(LoggingJobEventDelegate(logger: app.logger)) |
| 230 | + |
| 231 | + let userTokenCleanerJob = UserTokenClearUpJob(userTokenClearing: UserTokenClearer(database: app.db)) |
| 232 | + app.queues.schedule(userTokenCleanerJob) |
| 233 | + .daily() |
| 234 | + |
| 235 | + try app.queues.startScheduledJobs() |
| 236 | + try app.queues.startInProcessJobs() |
| 237 | +} |
0 commit comments