Ajout d'un système de cache des

requêtes HTTP
This commit is contained in:
Sébastien André
2019-11-19 22:42:43 +01:00
parent fb2699f974
commit 53ff769188
15 changed files with 257 additions and 164 deletions

View File

@@ -1,20 +1,19 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from "@angular/core";
import { ServiceComm } from '../services/serviceComm'; import { ServiceComm } from "../services/service-comm.service";
@Component({ @Component({
selector: 'app-root', selector: "app-root",
templateUrl: './app.component.html', templateUrl: "./app.component.html",
styleUrls: ['./app.component.css'] styleUrls: ["./app.component.css"]
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
title = 'app'; title = "app";
showMenu = false; showMenu = false;
constructor(private serviceComm: ServiceComm) { constructor(private serviceComm: ServiceComm) {}
}
ngOnInit() { ngOnInit() {
this.serviceComm.componentTitle.subscribe(title => this.title = title); this.serviceComm.componentTitle.subscribe(title => (this.title = title));
} }
toggleMenu() { toggleMenu() {

View File

@@ -1,23 +1,23 @@
import { BrowserModule } from '@angular/platform-browser'; import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from '@angular/core'; import { NgModule } from "@angular/core";
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from "@angular/router";
import { HttpClientModule } from '@angular/common/http'; import { HttpClientModule, HTTP_INTERCEPTORS } from "@angular/common/http";
import { AppComponent } from './app.component'; import { AppComponent } from "./app.component";
import { SummaryComponent } from './summary/summary.component'; import { SummaryComponent } from "./summary/summary.component";
import { ListOfJumpsComponent } from './list-of-jumps/list-of-jumps.component'; import { ListOfJumpsComponent } from "./list-of-jumps/list-of-jumps.component";
import { ListOfDzsComponent } from './list-of-dzs/list-of-dzs.component'; import { ListOfDzsComponent } from "./list-of-dzs/list-of-dzs.component";
import { NewJumpComponent } from './new-jump/new-jump.component'; import { NewJumpComponent } from "./new-jump/new-jump.component";
import { ListOfAircraftsComponent } from './list-of-aircrafts/list-of-aircrafts.component'; import { ListOfAircraftsComponent } from "./list-of-aircrafts/list-of-aircrafts.component";
import { ListOfJumpTypesComponent } from './list-of-jump-types/list-of-jump-types.component'; import { ListOfJumpTypesComponent } from "./list-of-jump-types/list-of-jump-types.component";
import { DateService } from '../services/dateService'; import { DateService } from "../services/date.service";
import { ServiceApiGet } from '../services/serviceApiGet'; import { ServiceApiGet } from "../services/service-api-get.service";
import { ServiceApiPost } from '../services/serviceApiPost'; import { ServiceApiPost } from "../services/service-api-post.service";
import { ServiceComm } from '../services/serviceComm'; import { ServiceComm } from "../services/service-comm.service";
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { FormsModule } from '@angular/forms'; import { FormsModule } from "@angular/forms";
import { import {
MatPaginatorModule, MatPaginatorModule,
MatTableModule, MatTableModule,
@@ -30,20 +30,19 @@ import {
MatInputModule, MatInputModule,
MatButtonModule, MatButtonModule,
MatIconModule MatIconModule
} from '@angular/material'; } from "@angular/material";
import { RequestCache } from "../services/request-cache.service";
import { CachingInterceptor } from "../services/caching-interceptor.service";
const appRoutes: Routes = [ const appRoutes: Routes = [
{ path: 'summary', component: SummaryComponent }, { path: "summary", component: SummaryComponent },
{ path: 'jumpsList', component: ListOfJumpsComponent }, { path: "jumpsList", component: ListOfJumpsComponent },
{ path: 'dz', component: ListOfDzsComponent }, { path: "dz", component: ListOfDzsComponent },
{ path: 'newjump', component: NewJumpComponent }, { path: "newjump", component: NewJumpComponent },
{ path: 'aircraftList', component: ListOfAircraftsComponent }, { path: "aircraftList", component: ListOfAircraftsComponent },
{ path: 'jumpTypeList', component: ListOfJumpTypesComponent } { path: "jumpTypeList", component: ListOfJumpTypesComponent }
]; ];
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
@@ -75,7 +74,14 @@ const appRoutes: Routes = [
MatIconModule MatIconModule
], ],
exports: [HttpClientModule], exports: [HttpClientModule],
providers: [ServiceApiPost, ServiceApiGet, ServiceComm, DateService], providers: [
ServiceApiPost,
ServiceApiGet,
ServiceComm,
DateService,
RequestCache,
{ provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }
],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule {} export class AppModule {}

View File

@@ -1,32 +1,33 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from "@angular/core";
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from "@angular/material/paginator";
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from "@angular/material/table";
import { AircraftResp } from '../../models/aircraft'; import { AircraftResp } from "../../models/aircraft";
import { ServiceApiGet } from '../../services/serviceApiGet'; import { ServiceApiGet } from "../../services/service-api-get.service";
import { ServiceComm } from '../../services/serviceComm'; import { ServiceComm } from "../../services/service-comm.service";
@Component({ @Component({
selector: 'app-list-of-aircrafts', selector: "app-list-of-aircrafts",
templateUrl: './list-of-aircrafts.component.html', templateUrl: "./list-of-aircrafts.component.html",
styleUrls: ['./list-of-aircrafts.component.css'] styleUrls: ["./list-of-aircrafts.component.css"]
}) })
export class ListOfAircraftsComponent implements OnInit { export class ListOfAircraftsComponent implements OnInit {
public displayedColumns: Array<string> = ['id', 'name']; public displayedColumns: Array<string> = ["id", "name"];
public dataSourceTable; public dataSourceTable;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private serviceApi: ServiceApiGet, private serviceComm: ServiceComm) { constructor(
} private serviceApi: ServiceApiGet,
private serviceComm: ServiceComm
) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('List of aircrafts'); this.serviceComm.updatedComponentTitle("List of aircrafts");
this.getListOfAircrafts(); this.getListOfAircrafts();
} }
getListOfAircrafts() { getListOfAircrafts() {
this.serviceApi.getListOfAircrafts() this.serviceApi.getListOfAircrafts().subscribe(data => {
.subscribe(data => {
this.dataSourceTable = new MatTableDataSource<AircraftResp>(data); this.dataSourceTable = new MatTableDataSource<AircraftResp>(data);
this.dataSourceTable.paginator = this.paginator; this.dataSourceTable.paginator = this.paginator;
}); });

View File

@@ -1,35 +1,41 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from "@angular/core";
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from "@angular/material/paginator";
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from "@angular/material/table";
import { DropZoneResp } from '../../models/dropzone'; import { DropZoneResp } from "../../models/dropzone";
import { ServiceApiGet } from '../../services/serviceApiGet'; import { ServiceApiGet } from "../../services/service-api-get.service";
import { ServiceComm } from '../../services/serviceComm'; import { ServiceComm } from "../../services/service-comm.service";
@Component({ @Component({
selector: 'app-list-of-dzs', selector: "app-list-of-dzs",
templateUrl: './list-of-dzs.component.html', templateUrl: "./list-of-dzs.component.html",
styleUrls: ['./list-of-dzs.component.css'] styleUrls: ["./list-of-dzs.component.css"]
}) })
export class ListOfDzsComponent implements OnInit { export class ListOfDzsComponent implements OnInit {
public displayedColumns: Array<string> = ['id', 'name', 'latitude', 'longitude', 'address', 'email', 'type']; public displayedColumns: Array<string> = [
"id",
"name",
"latitude",
"longitude",
"address",
"email",
"type"
];
public dataSourceTable; public dataSourceTable;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private serviceApi: ServiceApiGet, constructor(
private serviceComm: ServiceComm) { private serviceApi: ServiceApiGet,
} private serviceComm: ServiceComm
) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('List of DZs'); this.serviceComm.updatedComponentTitle("List of DZs");
this.getListOfDropZones(); this.getListOfDropZones();
} }
getListOfDropZones() { getListOfDropZones() {
this.serviceApi.getListOfDropZones() this.serviceApi.getListOfDropZones().subscribe(data => {
.subscribe(data => {
this.dataSourceTable = new MatTableDataSource<DropZoneResp>(data); this.dataSourceTable = new MatTableDataSource<DropZoneResp>(data);
this.dataSourceTable.paginator = this.paginator; this.dataSourceTable.paginator = this.paginator;
}); });

View File

@@ -1,32 +1,33 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from "@angular/core";
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from "@angular/material/paginator";
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from "@angular/material/table";
import { JumpTypeResp } from '../../models/jumpType'; import { JumpTypeResp } from "../../models/jumpType";
import { ServiceApiGet } from '../../services/serviceApiGet'; import { ServiceApiGet } from "../../services/service-api-get.service";
import { ServiceComm } from '../../services/serviceComm'; import { ServiceComm } from "../../services/service-comm.service";
@Component({ @Component({
selector: 'app-list-of-jump-types', selector: "app-list-of-jump-types",
templateUrl: './list-of-jump-types.component.html', templateUrl: "./list-of-jump-types.component.html",
styleUrls: ['./list-of-jump-types.component.css'] styleUrls: ["./list-of-jump-types.component.css"]
}) })
export class ListOfJumpTypesComponent implements OnInit { export class ListOfJumpTypesComponent implements OnInit {
public displayedColumns: Array<string> = ['id', 'name']; public displayedColumns: Array<string> = ["id", "name"];
public dataSourceTable; public dataSourceTable;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private serviceApi: ServiceApiGet, private serviceComm: ServiceComm) { constructor(
} private serviceApi: ServiceApiGet,
private serviceComm: ServiceComm
) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('List of jump types'); this.serviceComm.updatedComponentTitle("List of jump types");
this.getListOfJumpTypes(); this.getListOfJumpTypes();
} }
getListOfJumpTypes() { getListOfJumpTypes() {
this.serviceApi.getListOfJumpTypes() this.serviceApi.getListOfJumpTypes().subscribe(data => {
.subscribe(data => {
this.dataSourceTable = new MatTableDataSource<JumpTypeResp>(data); this.dataSourceTable = new MatTableDataSource<JumpTypeResp>(data);
this.dataSourceTable.paginator = this.paginator; this.dataSourceTable.paginator = this.paginator;
}); });

View File

@@ -1,29 +1,36 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from "@angular/core";
import { MatPaginator } from '@angular/material/paginator'; import { MatPaginator } from "@angular/material/paginator";
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from "@angular/material/table";
import { Observable } from 'rxjs';
import { JumpResp } from '../../models/jump';
import { ServiceApiGet } from '../../services/serviceApiGet';
import { ServiceComm } from '../../services/serviceComm';
import { Observable } from "rxjs";
import { JumpResp } from "../../models/jump";
import { ServiceApiGet } from "../../services/service-api-get.service";
import { ServiceComm } from "../../services/service-comm.service";
@Component({ @Component({
selector: 'app-list-of-jumps', selector: "app-list-of-jumps",
templateUrl: './list-of-jumps.component.html', templateUrl: "./list-of-jumps.component.html",
styleUrls: ['./list-of-jumps.component.css'] styleUrls: ["./list-of-jumps.component.css"]
}) })
export class ListOfJumpsComponent implements OnInit { export class ListOfJumpsComponent implements OnInit {
public listOfJumps: Observable<Array<JumpResp>>; public listOfJumps: Observable<Array<JumpResp>>;
public displayedColumns: Array<string> = ['id', 'jumpDate', 'jumpTypeId', 'aircraftId', 'dropZoneId',]; public displayedColumns: Array<string> = [
"id",
"jumpDate",
"jumpTypeId",
"aircraftId",
"dropZoneId"
];
public dataSourceTable; public dataSourceTable;
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
constructor(private serviceApi: ServiceApiGet, private serviceComm: ServiceComm) { constructor(
} private serviceApi: ServiceApiGet,
private serviceComm: ServiceComm
) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('List of jumps'); this.serviceComm.updatedComponentTitle("List of jumps");
this.getListOfJumps(); this.getListOfJumps();
} }

View File

@@ -1,17 +1,16 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from "@angular/core";
import { ServiceComm } from '../../services/serviceComm'; import { ServiceComm } from "../../services/service-comm.service";
import { ServiceApiGet } from '../../services/serviceApiGet'; import { ServiceApiGet } from "../../services/service-api-get.service";
import { ServiceApiPost } from '../../services/serviceApiPost'; import { ServiceApiPost } from "../../services/service-api-post.service";
import { JumpTypeResp } from '../../models/jumpType'; import { JumpTypeResp } from "../../models/jumpType";
import { AircraftResp } from '../../models/aircraft'; import { AircraftResp } from "../../models/aircraft";
import { DropZoneResp } from '../../models/dropzone'; import { DropZoneResp } from "../../models/dropzone";
import { DateService } from '../../services/dateService'; import { DateService } from "../../services/date.service";
@Component({ @Component({
selector: 'app-new-jump', selector: "app-new-jump",
templateUrl: './new-jump.component.html', templateUrl: "./new-jump.component.html",
styleUrls: ['./new-jump.component.css'] styleUrls: ["./new-jump.component.css"]
}) })
export class NewJumpComponent implements OnInit { export class NewJumpComponent implements OnInit {
beginDate: Date; beginDate: Date;
@@ -28,14 +27,15 @@ export class NewJumpComponent implements OnInit {
listOfAircraft: Array<AircraftResp>; listOfAircraft: Array<AircraftResp>;
listOfDropZone: Array<DropZoneResp>; listOfDropZone: Array<DropZoneResp>;
constructor(private serviceComm: ServiceComm, constructor(
private serviceComm: ServiceComm,
private serviceApiGet: ServiceApiGet, private serviceApiGet: ServiceApiGet,
private serviceApiPost: ServiceApiPost, private serviceApiPost: ServiceApiPost,
private dateService: DateService) { private dateService: DateService
} ) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('Add a new jump'); this.serviceComm.updatedComponentTitle("Add a new jump");
this.endDate = new Date(); this.endDate = new Date();
@@ -64,8 +64,7 @@ export class NewJumpComponent implements OnInit {
} }
private getListOfJumpTypes() { private getListOfJumpTypes() {
this.serviceApiGet.getListOfJumpTypes() this.serviceApiGet.getListOfJumpTypes().subscribe(data => {
.subscribe(data => {
this.listOfJumpType = data; this.listOfJumpType = data;
this.getListOfAircrafts(); this.getListOfAircrafts();
this.getListOfDropZones(); this.getListOfDropZones();
@@ -73,15 +72,13 @@ export class NewJumpComponent implements OnInit {
} }
private getListOfAircrafts() { private getListOfAircrafts() {
this.serviceApiGet.getListOfAircrafts() this.serviceApiGet.getListOfAircrafts().subscribe(data => {
.subscribe(data => {
this.listOfAircraft = data; this.listOfAircraft = data;
}); });
} }
private getListOfDropZones() { private getListOfDropZones() {
this.serviceApiGet.getListOfDropZones() this.serviceApiGet.getListOfDropZones().subscribe(data => {
.subscribe(data => {
this.listOfDropZone = data; this.listOfDropZone = data;
}); });
} }

View File

@@ -1,25 +1,26 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from "@angular/core";
import { ServiceComm } from '../../services/serviceComm'; import { ServiceComm } from "../../services/service-comm.service";
import { ServiceApiGet } from '../../services/serviceApiGet'; import { ServiceApiGet } from "../../services/service-api-get.service";
@Component({ @Component({
selector: 'app-summary', selector: "app-summary",
templateUrl: './summary.component.html', templateUrl: "./summary.component.html",
styleUrls: ['./summary.component.css'] styleUrls: ["./summary.component.css"]
}) })
export class SummaryComponent implements OnInit { export class SummaryComponent implements OnInit {
public displayedColumns: Array<string> = ['label', 'nb']; public displayedColumns: Array<string> = ["label", "nb"];
public dsNbJumpByDz; public dsNbJumpByDz;
public dsNbJumpByAircraft; public dsNbJumpByAircraft;
public dsNbJumpByRig; public dsNbJumpByRig;
public dsNbJumpByType; public dsNbJumpByType;
public dsNbJumpByYear; public dsNbJumpByYear;
constructor(private serviceApi: ServiceApiGet, constructor(
private serviceComm: ServiceComm) { } private serviceApi: ServiceApiGet,
private serviceComm: ServiceComm
) {}
ngOnInit() { ngOnInit() {
this.serviceComm.updatedComponentTitle('Summary'); this.serviceComm.updatedComponentTitle("Summary");
} }
} }

View File

@@ -0,0 +1,39 @@
import { Injectable } from "@angular/core";
import {
HttpEvent,
HttpRequest,
HttpResponse,
HttpInterceptor,
HttpHandler
} from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import { startWith, tap } from "rxjs/operators";
import "rxjs/add/observable/of";
import { RequestCache } from "./request-cache.service";
@Injectable()
export class CachingInterceptor implements HttpInterceptor {
constructor(private cache: RequestCache) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const cachedResponse = this.cache.get(req);
return cachedResponse
? Observable.of(cachedResponse)
: this.sendRequest(req, next);
}
sendRequest(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
tap(event => {
if (event instanceof HttpResponse) {
this.cache.put(req, event);
}
})
);
}
}

View File

@@ -0,0 +1,35 @@
import { Injectable } from "@angular/core";
import { HttpRequest, HttpResponse } from "@angular/common/http";
const maxAge = 30000;
@Injectable()
export class RequestCache {
cache = new Map();
get(req: HttpRequest<any>): HttpResponse<any> | undefined {
const url = req.urlWithParams + "-" + req.method;
const cached = this.cache.get(url);
if (!cached) {
return undefined;
}
return cached.response;
}
put(req: HttpRequest<any>, response: HttpResponse<any>): void {
//const url = req.url;
const url = req.urlWithParams + "-" + req.method;
const entry = { url, response, lastRead: Date.now() };
this.cache.set(url, entry);
console.log(this.cache);
const expired = Date.now() - maxAge;
this.cache.forEach(expiredEntry => {
if (expiredEntry.lastRead < expired) {
this.cache.delete(expiredEntry.url);
}
});
}
}

View File

@@ -1,18 +1,17 @@
import { Injectable } from '@angular/core'; import { Injectable } from "@angular/core";
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from "@angular/common/http";
import { JumpReq } from '../models/jump'; import { JumpReq } from "../models/jump";
import { environment } from '../environments/environment'; import { environment } from "../environments/environment";
import { DateService } from './dateService'; import { DateService } from "./date.service";
@Injectable() @Injectable()
export class ServiceApiPost { export class ServiceApiPost {
private readonly headers = new HttpHeaders({ private readonly headers = new HttpHeaders({
'Access-Control-Allow-Origin': environment.urlApi "Access-Control-Allow-Origin": environment.urlApi
}); });
constructor(private http: HttpClient, constructor(private http: HttpClient, private dateService: DateService) {}
private dateService: DateService) { }
public AddListOfJump( public AddListOfJump(
selectedJumpType: number, selectedJumpType: number,
@@ -26,7 +25,8 @@ export class ServiceApiPost {
defaultDeployAltitude: number, defaultDeployAltitude: number,
countOfJumps: number countOfJumps: number
) { ) {
const diffInDays = this.dateService.DiffBetweenDates(beginDate, endDate) + 1; const diffInDays =
this.dateService.DiffBetweenDates(beginDate, endDate) + 1;
const countOfJumpsPerDay = Math.trunc(countOfJumps / diffInDays); const countOfJumpsPerDay = Math.trunc(countOfJumps / diffInDays);
for (let i = 1; beginDate.getTime() < endDate.getTime(); i++) { for (let i = 1; beginDate.getTime() < endDate.getTime(); i++) {
@@ -79,15 +79,16 @@ export class ServiceApiPost {
exitAltitude: defaultExitAltitude, exitAltitude: defaultExitAltitude,
deployAltitude: defaultDeployAltitude, deployAltitude: defaultDeployAltitude,
gearId: selectedRig, gearId: selectedRig,
notes: '', notes: "",
id: 0, id: 0,
jumpDate: jumpDate jumpDate: jumpDate
}; };
// console.log(bodyNewjump.jumpDate); // console.log(bodyNewjump.jumpDate);
this.http.post(`${environment.urlApi}/api/Jump`, this.http
bodyNewjump, .post(`${environment.urlApi}/api/Jump`, bodyNewjump, {
{ headers: this.headers }) headers: this.headers
})
.subscribe(data => console.log(data)); .subscribe(data => console.log(data));
} }
} }