Skip to content

perf, lazy-load Mutex #9598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions components/legacy/scope/component-ops/scope-components-importer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ComponentID, ComponentIdList } from '@teambit/component-id';
import { Mutex, withTimeout } from 'async-mutex';
import { Mutex, withTimeout, MutexInterface } from 'async-mutex';
import mapSeries from 'p-map-series';
import { DEFAULT_LANE, LaneId } from '@teambit/lane-id';
import { BitError } from '@teambit/bit-error';
Expand Down Expand Up @@ -47,16 +47,8 @@ export class ScopeComponentsImporter {
private static instancePerScope: { [scopeName: string]: ScopeComponentsImporter } = {};
private sources: SourcesRepository;
private repo: Repository;
private fetchWithDepsMutex = withTimeout(
new Mutex(),
TIMEOUT_FOR_MUTEX,
new BitError(`error: fetch-with-dependencies timeout exceeded (${TIMEOUT_FOR_MUTEX} minutes)`)
);
private importManyObjectsMutex = withTimeout(
new Mutex(),
TIMEOUT_FOR_MUTEX,
new BitError(`error: fetch-multiple-objects timeout exceeded (${TIMEOUT_FOR_MUTEX} minutes)`)
);
private _fetchWithDepsMutex?: MutexInterface;
private _importManyObjectsMutex?: MutexInterface;
/**
* important!
* refrain from using this. it's a workaround for bare-scopes to import from the lane when the call is
Expand All @@ -71,6 +63,29 @@ export class ScopeComponentsImporter {
this.repo = scope.objects;
}

private get fetchWithDepsMutex(): MutexInterface {
if (!this._fetchWithDepsMutex) {
this._fetchWithDepsMutex = withTimeout(
new Mutex(),
TIMEOUT_FOR_MUTEX,
new BitError(`error: fetch-with-dependencies timeout exceeded (${TIMEOUT_FOR_MUTEX} minutes)`)
);
}
return this._fetchWithDepsMutex;
}

private get importManyObjectsMutex(): MutexInterface {
if (!this._importManyObjectsMutex) {
this._importManyObjectsMutex = withTimeout(
new Mutex(),
TIMEOUT_FOR_MUTEX,
new BitError(`error: fetch-multiple-objects timeout exceeded (${TIMEOUT_FOR_MUTEX} minutes)`)
);
}
return this._importManyObjectsMutex;
}


static getInstance(scope: Scope): ScopeComponentsImporter {
if (!this.instancePerScope[scope.name]) {
this.instancePerScope[scope.name] = new ScopeComponentsImporter(scope);
Expand Down
8 changes: 7 additions & 1 deletion components/legacy/scope/lanes/remote-lanes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,16 @@ export class RemoteLanes {
basePath: string;
private remotes: { [remoteName: string]: Lanes } = {};
private changed: { [remoteName: string]: { [laneName: string]: boolean } } = {};
writeMutex = new Mutex();
private _writeMutex?: Mutex;
constructor(scopePath: string) {
this.basePath = path.join(scopePath, REMOTE_REFS_DIR);
}
get writeMutex() {
if (!this._writeMutex) {
this._writeMutex = new Mutex();
}
return this._writeMutex;
}
async addEntry(remoteLaneId: LaneId, componentId: ComponentID, head?: Ref) {
if (!remoteLaneId) throw new TypeError('addEntry expects to get remoteLaneId');
if (!head) return; // do nothing
Expand Down
9 changes: 8 additions & 1 deletion scopes/scope/objects/models/model-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export default class Component extends BitObject {
schema: string | undefined;
detachedHeads: DetachedHeads;
private divergeData?: SnapsDistance;
private populateVersionHistoryMutex = new Mutex();
private _populateVersionHistoryMutex?: Mutex;
constructor(props: ComponentProps) {
super();
if (!props.name) throw new TypeError('Model Component constructor expects to get a name parameter');
Expand All @@ -163,6 +163,13 @@ export default class Component extends BitObject {
this.detachedHeads = props.detachedHeads || new DetachedHeads();
}

private get populateVersionHistoryMutex() {
if (!this._populateVersionHistoryMutex) {
this._populateVersionHistoryMutex = new Mutex();
}
return this._populateVersionHistoryMutex;
}

get versionArray(): Ref[] {
return Object.values(this.versions);
}
Expand Down
9 changes: 8 additions & 1 deletion scopes/scope/objects/objects/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class Repository {
protected cache: InMemoryCache<BitObject>;
remoteLanes!: RemoteLanes;
unmergedComponents!: UnmergedComponents;
persistMutex = new Mutex();
_persistMutex?: Mutex;
constructor(scopePath: string, scopeJson: ScopeJson) {
this.scopePath = scopePath;
this.scopeJson = scopeJson;
Expand All @@ -53,6 +53,13 @@ export default class Repository {
this.cache = createInMemoryCache({ maxSize: getMaxSizeForObjects() });
}

get persistMutex() {
if (!this._persistMutex) {
this._persistMutex = new Mutex();
}
return this._persistMutex;
}

static async load({ scopePath, scopeJson }: { scopePath: string; scopeJson: ScopeJson }): Promise<Repository> {
const repository = new Repository(scopePath, scopeJson);
await repository.init();
Expand Down
8 changes: 7 additions & 1 deletion scopes/scope/objects/objects/scope-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,17 @@ type Index = { [IndexType.components]: ComponentItem[]; [IndexType.lanes]: LaneI
export class ScopeIndex {
indexPath: string;
index: Index;
writeIndexMutex = new Mutex();
_writeIndexMutex?: Mutex;
constructor(indexPath: string, index: Index = { [IndexType.components]: [], [IndexType.lanes]: [] }) {
this.indexPath = indexPath;
this.index = index;
}
get writeIndexMutex() {
if (!this._writeIndexMutex) {
this._writeIndexMutex = new Mutex();
}
return this._writeIndexMutex;
}
static async load(basePath: string): Promise<ScopeIndex> {
const indexPath = this._composePath(basePath);
try {
Expand Down