committed by
GitHub
117 changed files with 1020 additions and 490 deletions
@ -0,0 +1,24 @@ |
|||
/** |
|||
* Copyright © 2016-2024 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.common.data.exception; |
|||
|
|||
public class EntityVersionMismatchException extends RuntimeException { |
|||
|
|||
public EntityVersionMismatchException(String message, Throwable cause) { |
|||
super(message, cause); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
/** |
|||
* Copyright © 2016-2024 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
package org.thingsboard.server.dao.entity; |
|||
|
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.thingsboard.server.cache.VersionedTbCache; |
|||
import org.thingsboard.server.common.data.HasVersion; |
|||
|
|||
import java.io.Serializable; |
|||
|
|||
public abstract class CachedVersionedEntityService<K extends Serializable, V extends Serializable & HasVersion, E> extends AbstractCachedEntityService<K, V, E> { |
|||
|
|||
@Autowired |
|||
protected VersionedTbCache<K, V> cache; |
|||
|
|||
} |
|||
@ -0,0 +1,90 @@ |
|||
///
|
|||
/// Copyright © 2016-2024 The Thingsboard Authors
|
|||
///
|
|||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|||
/// you may not use this file except in compliance with the License.
|
|||
/// You may obtain a copy of the License at
|
|||
///
|
|||
/// http://www.apache.org/licenses/LICENSE-2.0
|
|||
///
|
|||
/// Unless required by applicable law or agreed to in writing, software
|
|||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
/// See the License for the specific language governing permissions and
|
|||
/// limitations under the License.
|
|||
///
|
|||
|
|||
import { Injectable } from '@angular/core'; |
|||
import { |
|||
HttpErrorResponse, |
|||
HttpEvent, |
|||
HttpHandler, |
|||
HttpInterceptor, |
|||
HttpRequest, |
|||
HttpStatusCode |
|||
} from '@angular/common/http'; |
|||
import { Observable, of, throwError } from 'rxjs'; |
|||
import { catchError, switchMap } from 'rxjs/operators'; |
|||
import { MatDialog } from '@angular/material/dialog'; |
|||
import { |
|||
EntityConflictDialogComponent |
|||
} from '@shared/components/dialog/entity-conflict-dialog/entity-conflict-dialog.component'; |
|||
import { HasId } from '@shared/models/base-data'; |
|||
import { HasVersion } from '@shared/models/entity.models'; |
|||
import { getInterceptorConfig } from './interceptor.util'; |
|||
|
|||
@Injectable() |
|||
export class EntityConflictInterceptor implements HttpInterceptor { |
|||
|
|||
constructor( |
|||
private dialog: MatDialog, |
|||
) {} |
|||
|
|||
intercept(request: HttpRequest<unknown & HasId & HasVersion>, next: HttpHandler): Observable<HttpEvent<unknown>> { |
|||
if (!request.url.startsWith('/api/')) { |
|||
return next.handle(request); |
|||
} |
|||
|
|||
return next.handle(request).pipe( |
|||
catchError((error: HttpErrorResponse) => { |
|||
if (error.status !== HttpStatusCode.Conflict) { |
|||
return throwError(() => error); |
|||
} |
|||
|
|||
return this.handleConflictError(request, next, error); |
|||
}) |
|||
); |
|||
} |
|||
|
|||
private handleConflictError( |
|||
request: HttpRequest<unknown & HasId & HasVersion>, |
|||
next: HttpHandler, |
|||
error: HttpErrorResponse |
|||
): Observable<HttpEvent<unknown>> { |
|||
if (getInterceptorConfig(request).ignoreVersionConflict) { |
|||
return throwError(() => error); |
|||
} |
|||
|
|||
return this.openConflictDialog(request.body, error.error.message).pipe( |
|||
switchMap(result => { |
|||
if (result) { |
|||
return next.handle(this.updateRequestVersion(request)); |
|||
} |
|||
return of(null); |
|||
}) |
|||
); |
|||
} |
|||
|
|||
private updateRequestVersion(request: HttpRequest<unknown & HasId & HasVersion>): HttpRequest<unknown & HasId & HasVersion> { |
|||
const body = { ...request.body, version: null }; |
|||
return request.clone({ body }); |
|||
} |
|||
|
|||
private openConflictDialog(entity: unknown & HasId & HasVersion, message: string): Observable<boolean> { |
|||
const dialogRef = this.dialog.open(EntityConflictDialogComponent, { |
|||
data: { message, entity } |
|||
}); |
|||
|
|||
return dialogRef.afterClosed(); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue