9. 스캐터-개더 부분 응답을 완전 응답으로 오인 + 무경계 팬아웃·집계 경합 (C#)
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 시나리오: 글로벌 경제 감시 서비스가 모든 샤드(존) 서버에 질의해 "전 서버 재화 총량"을
// 합산한다. 이 값은 인플레이션 감시·재화 환수/지급 정책 판단 같은 권위 있는 결정에 쓰인다.
// 코디네이터는 각 샤드에 부분 합계를 요청하고(팬아웃) 응답을 모아 더한다(개더).
//
// 요구사항:
// - 결과는 "전 샤드를 반영한 값"이어야 하며, 일부 샤드가 응답하지 않으면
// 그 사실이 드러나야 한다(불완전한 값을 완전한 값처럼 쓰면 안 됨).
// - 샤드 하나가 느리거나 죽어도 코디네이터가 무한정 매달리면 안 된다.
//
// 과제: (A)(B) 지점을 검토하라. 샤드 장애·지연 시 결과가 조용히 틀리거나
// 집계가 깨질 수 있다. 어떤 상황에서 그런지 밝히고 고쳐라.
using System.Collections.Generic;
using System.Threading.Tasks;
public interface IShardClient
{
Task<ulong> QueryCurrencyTotalAsync(); // 이 샤드 재화 총량(네트워크). 실패 시 예외 가능
}
public sealed class EconomyMonitor
{
private readonly IReadOnlyList<IShardClient> _shards;
public EconomyMonitor(IReadOnlyList<IShardClient> shards) => _shards = shards;
public async Task<ulong> GlobalCurrencyTotalAsync()
{
ulong total = 0;
var tasks = new List<Task>();
foreach (var sc in _shards)
{
tasks.Add(Task.Run(async () =>
{
try
{
ulong part = await sc.QueryCurrencyTotalAsync(); // 타임아웃 없음
total += part; // (B)
}
catch { /* 실패 샤드는 건너뜀 */ }
}));
}
await Task.WhenAll(tasks); // 전 샤드 대기
return total; // (A)
}
} 결함 코드 · C++
// 시나리오: 글로벌 경제 감시 서비스가 모든 샤드(존) 서버에 질의해 "전 서버 재화 총량"을
// 합산한다. 이 값은 인플레이션 감시·재화 환수/지급 정책 판단 같은 권위 있는 결정에 쓰인다.
// 코디네이터는 각 샤드에 부분 합계를 요청하고(팬아웃) 응답을 모아 더한다(개더).
//
// 요구사항:
// - 결과는 "전 샤드를 반영한 값"이어야 하며, 일부 샤드가 응답하지 않으면
// 그 사실이 드러나야 한다(불완전한 값을 완전한 값처럼 쓰면 안 됨).
// - 샤드 하나가 느리거나 죽어도 코디네이터가 무한정 매달리면 안 된다.
//
// 과제: (A)(B) 지점을 검토하라. 샤드 장애·지연 시 결과가 조용히 틀리거나
// 집계가 깨질 수 있다. 어떤 상황에서 그런지 밝히고 고쳐라.
#include <cstdint>
#include <vector>
#include <future>
struct ShardClient {
uint64_t queryCurrencyTotal(); // 이 샤드의 재화 총량(네트워크 호출). 실패 시 예외 가능
bool reachable() const;
};
class EconomyMonitor {
public:
explicit EconomyMonitor(std::vector<ShardClient*> shards) : shards_(shards) {}
uint64_t globalCurrencyTotal() {
uint64_t total = 0;
std::vector<std::future<void>> tasks;
for (ShardClient* sc : shards_) {
tasks.push_back(std::async(std::launch::async, [&total, sc] {
uint64_t part = sc->queryCurrencyTotal(); // 타임아웃 없음
total += part; // (B)
}));
}
for (auto& t : tasks) t.wait(); // 전 샤드 응답 대기
return total; // (A)
}
private:
std::vector<ShardClient*> shards_;
}; 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.
내 리뷰 · C++
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.