1- import { UrlShortenerService } from '../urlShortener' ;
1+ import { UrlShortenerService } from './. ./urlShortener' ;
22import { KeyGenerationServiceImpl } from './keyGeneration' ;
33import { KeyGeneration } from '../keyGeneration' ;
44import config from '../../config' ;
@@ -13,10 +13,22 @@ export class UrlShortenerServiceImpl implements UrlShortenerService {
1313 private urlDao : UrlDao ;
1414 private redis : MemoryStore ;
1515
16- constructor ( ) {
17- this . redis = Redis . getInstance ( ) ;
18- this . keyGenerationService = new KeyGenerationServiceImpl ( ) ;
19- this . urlDao = new UrlDaoImpl ( ) ;
16+ constructor (
17+ urlDao : UrlDao ,
18+ keyGenerationService : KeyGeneration ,
19+ redis : MemoryStore
20+ ) {
21+ this . redis = redis ;
22+ this . keyGenerationService = keyGenerationService ;
23+ this . urlDao = urlDao ;
24+ }
25+
26+ public static defaultImpl ( ) : UrlShortenerService {
27+ return new UrlShortenerServiceImpl (
28+ new UrlDaoImpl ( ) ,
29+ new KeyGenerationServiceImpl ( ) ,
30+ Redis . getInstance ( )
31+ ) ;
2032 }
2133
2234 public async shortenUrl (
@@ -28,6 +40,11 @@ export class UrlShortenerServiceImpl implements UrlShortenerService {
2840 await this . ensureAliasDoesNotExist ( alias ) ;
2941 key = urlSafe ( alias ) ;
3042 } else {
43+ // If key exists, return it, don't store additional records
44+ const urlKey = await this . getUrlKeyFromDb ( originalUrl ) ;
45+ if ( urlKey ) {
46+ return this . constructShortenedUrl ( urlKey ) ;
47+ }
3148 key = await this . getAvailableKey ( ) ;
3249 }
3350
@@ -39,11 +56,28 @@ export class UrlShortenerServiceImpl implements UrlShortenerService {
3956 return this . constructShortenedUrl ( key ) ;
4057 }
4158
59+ public async getUrlKeyFromDb ( originalUrl : string ) : Promise < string > {
60+ const urls = await this . urlDao . findByOriginalUrl ( originalUrl ) ;
61+ if ( ! urls ) {
62+ logger . info (
63+ `Original url ${ originalUrl } is not found in database. Returning undefined`
64+ ) ;
65+ return undefined ;
66+ }
67+ if ( urls && urls . length ) {
68+ const urlKey = urls [ 0 ] . id ;
69+ logger . info (
70+ `Original url ${ originalUrl } is found in database, returning url key ${ urlKey } `
71+ ) ;
72+ return urlKey ;
73+ }
74+ }
75+
4276 public async getOriginalUrl ( urlKey : string ) : Promise < string > {
4377 const cachedData = await this . redis . getString ( urlKey ) ;
4478 // TODO: Test. Log cache hit or miss
4579 if ( cachedData ) {
46- logger . info ( `Found short URL ${ urlKey } from cache` ) ;
80+ logger . info ( `Found url key ${ urlKey } from cache. Returning original url ` ) ;
4781 return cachedData ;
4882 }
4983
@@ -52,11 +86,11 @@ export class UrlShortenerServiceImpl implements UrlShortenerService {
5286 ) ;
5387 const urlInDb = await this . urlDao . findById ( urlKey ) ;
5488 if ( ! urlInDb ) {
55- throwError ( {
56- status : ErrorCode . NOT_FOUND ,
57- message : `/${ urlKey } does not exist` ,
58- } ) ;
89+ return undefined ;
5990 }
91+ logger . info (
92+ `Setting url key ${ urlKey } and original url ${ urlInDb . originalUrl } in cache`
93+ ) ;
6094 await this . redis . setString ( urlKey , urlInDb . originalUrl ) ;
6195 return urlInDb . originalUrl ;
6296 }
0 commit comments