Scatter-Gather pattern

Scatter-Gather pattern

architekturanávrhové vzory

Headshot Bronislav Klučka, 26. 9. 2025 09:44

Scatter-Gather je další z rodiny návrhových vzorů, které se věnují separation of concern - oddělení zodpovědnosti. Hlavním přínosem scatter-gather vzoru je paralelizace - možnost vykonávat několik operací najednou a je tedy vhodný pro prostředí, jazyky, které paralelizaci nabízejí, mají thready, workery, nebo umí spustit nové procesy.

Jako vždy začneme ukázkami:

Příklad: spam filter

Spam filter už jsme dělali, ale podíváme na něj znovu trochu jinak.

Pravidla:

  • potřebujeme zkontrolovat obsah emailu proti spam filteru

  • potřebujeme zkontrolovat hlavičky emailu (DKIM, SPF, …)

  • potřebujeme zkontrolovat odesilatele

Pseudo-implementace - rules engine

interface Email {
	text: string;
	sender: string;
	headers: string[];
}

interface SpamRule {
	/**
	 * function accepting email and returning score modifier
	 * @param email
	 * @returns
	 */
	processEmail: (email: Email) => number;
}

class SpamEngine {
	protected rules: SpamRule[] = [];

	addRules(rules: SpamRule[]) {
		this.rules.push(...rules);
	}

	execute(email: Email): boolean {
		const score = this.rules.reduce((acc, rule) => {
			return acc + rule.processEmail(email);
		}, 0);
		return score > 0;
	}
}

class SpamText implements SpamRule {
	processEmail(email: Email): number {
		// process
		return 1;
	}
}

class SpamSender implements SpamRule {
	processEmail(email: Email): number {
		// process
		return 1;
	}
}

class SpamHeaders implements SpamRule {
	processEmail(email: Email): number {
		// process
		return 1;
	}
}

/************************************
 * programm.mts
 */

const spamEngine = new SpamEngine();
spamEngine.addRules([
	new SpamText(),
	new SpamSender(),
	new SpamHeaders(),
]);

console.log(spamEngine.execute({
	sender: 'john.doe@company.com',
	headers: ['from: john.doe@company.com'],
	text: 'this is spam',
}));

Výše uvedená implementace je naprosto v pořádku, nicméně má jednu nevýhodu: procesy běží sériově jeden za druhým. V některých případech, např. v pipeline patternu je potřeba zachovat pořadí, nicméně v tomto na pořadí nezáleží a tam může scatter-gather zrychlit processing.

Scatter-Gather

Scatter-Gather

Podstata scatter-gather patternu je v tom, že na místo toho, aby kód prováděl výpočet sám v hlavním vlákně deleguje výpočet na paralelní procesy.

Úprava příkladu, který jsme měli by byla velmi jednoduchá:

Pseudo-implementace - scatter gather



interface Email {
	text: string;
	sender: string;
	headers: string[];
}


interface SpamRule {
	/**
	 * function accepting email and returning score modifier
	 * @param email
	 * @returns
	 */
	processEmail: (email: Email) => Promise<number>
}

class SpamScatterGather {
	protected rules: SpamRule[] = [];

	addRules(rules: SpamRule[]) {
		this.rules.push(...rules);
	}

	async execute(email: Email): Promise<boolean> {
		// parallel processing
		// process all requests in parallel and wait until completion to continue
		const scores = await Promise.all(this.rules.map(rule => rule.processEmail(email)));
		const score = scores.reduce((acc, cur) => {
			return acc + cur;
		}, 0);
		return score > 0;
	}
}


class SpamText implements SpamRule {
	async processEmail(email: Email): Promise<number> {
		// process
		return 1;
	}
}

class SpamSender implements SpamRule {
	async processEmail(email: Email): Promise<number> {
		// process
		return 1;
	}
}

class SpamHeaders implements SpamRule {
	async processEmail(email: Email): Promise<number> {
		// process
		return 1;
	}
}


/************************************
 * programm.mts
 */

const spamSG = new SpamScatterGather();
spamSG.addRules([
	new SpamText(),
	new SpamSender(),
	new SpamHeaders(),
]);

console.log(await spamSG.execute({
	sender: 'john.doe@company.com',
	headers: ['from: john.doe@company.com'],
	text: 'this is spam',
}));

V závislosti na jazyce je to potom otázka náročnosti utilizace threadů/workerů/procesů.

Pro efektivní použití je nicméně důležité, aby se hlavní výpočetní zátěž nacházela v paralelizovaných procesech a ne v hlavním threadu vaší aplikace.

Headshot Bronislav Klučka, 26. 9. 2025 09:44

Komentáře

Napište komentář

Komentáře jsou schvalované, než se zobrazí na stránkách.

Nebylo možné přidat komentář.

Váš komentář byl přidán a čeká se na schválení.

Váš komentář je příliš dlouhý.

Používáme cookies a podobné technologie, jako Google Analytics, pro sběr analytických dat. To nám pomáhá pochopit, jak uživatelé používají naše stránky.

Více info

Stránky používají Google Analytics, a analytické služby poskytované společností Google. Google Analytics používá cookies, aby nám tato služba pomohla analyzovat, jak uživatelé používají naše stránky. Informace generované cookies, které se týkají vašeho používání stránek (včetně vaší IP adresy) budou přeneseny a uloženy u společnosti Google. Požíváme tato data pro vytváření reportů o aktivitě a k poskytování dalších služeb, které se týkají těchto stránek.

Analytická data nám pomáhají vylepšovat naše služby. Nepoužíváme je k marketingovým a reklamním účelům. Tato data nepředáváme ani neprodáváme dál.