Skip to content

Commit d1c7c39

Browse files
committed
More wip trying to make test containers more reliable
1 parent e1df4d0 commit d1c7c39

File tree

2 files changed

+59
-11
lines changed

2 files changed

+59
-11
lines changed

internal-packages/testcontainers/src/index.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ type PostgresContext = NetworkContext & {
1717
prisma: PrismaClient;
1818
};
1919

20-
type RedisContext = { redisContainer: StartedRedisContainer; redisOptions: RedisOptions };
20+
type RedisContext = NetworkContext & {
21+
redisContainer: StartedRedisContainer;
22+
redisOptions: RedisOptions;
23+
};
2124

2225
type ElectricContext = {
2326
electricOrigin: string;
@@ -71,9 +74,13 @@ const prisma = async (
7174

7275
export const postgresTest = test.extend<PostgresContext>({ network, postgresContainer, prisma });
7376

74-
const redisContainer = async ({}, use: Use<StartedRedisContainer>) => {
77+
const redisContainer = async (
78+
{ network }: { network: StartedNetwork },
79+
use: Use<StartedRedisContainer>
80+
) => {
7581
const { container } = await createRedisContainer({
7682
port: 6379,
83+
network,
7784
});
7885
try {
7986
await use(container);
@@ -97,20 +104,25 @@ const redisOptions = async (
97104
},
98105
connectTimeout: 10000, // 10 seconds
99106
// Add more robust connection options
100-
enableOfflineQueue: false,
107+
enableOfflineQueue: true,
101108
reconnectOnError: (err) => {
102109
const targetError = "READONLY";
103110
if (err.message.includes(targetError)) {
104111
return true;
105112
}
106113
return false;
107114
},
115+
enableAutoPipelining: true,
116+
autoResubscribe: true,
117+
autoResendUnfulfilledCommands: true,
118+
lazyConnect: false,
119+
showFriendlyErrorStack: true,
108120
};
109121

110122
await use(options);
111123
};
112124

113-
export const redisTest = test.extend<RedisContext>({ redisContainer, redisOptions });
125+
export const redisTest = test.extend<RedisContext>({ network, redisContainer, redisOptions });
114126

115127
const electricOrigin = async (
116128
{

internal-packages/testcontainers/src/utils.ts

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql";
2-
import { RedisContainer } from "@testcontainers/redis";
2+
import { RedisContainer, StartedRedisContainer } from "@testcontainers/redis";
3+
import Redis from "ioredis";
34
import path from "path";
45
import { GenericContainer, StartedNetwork, Wait } from "testcontainers";
56
import { x } from "tinyexec";
@@ -40,24 +41,59 @@ export async function createPostgresContainer(network: StartedNetwork) {
4041
return { url: container.getConnectionUri(), container, network };
4142
}
4243

43-
export async function createRedisContainer({ port }: { port?: number }) {
44-
const container = await new RedisContainer()
45-
.withExposedPorts(port ?? 6379)
46-
.withStartupTimeout(120_000) // 2 minutes
44+
export async function createRedisContainer({
45+
port,
46+
network,
47+
}: {
48+
port?: number;
49+
network?: StartedNetwork;
50+
}) {
51+
let container = new RedisContainer().withExposedPorts(port ?? 6379).withStartupTimeout(120_000); // 2 minutes
52+
53+
if (network) {
54+
container = container.withNetwork(network).withNetworkAliases("redis");
55+
}
56+
57+
const startedContainer = await container
4758
.withHealthCheck({
4859
test: ["CMD", "redis-cli", "ping"],
4960
interval: 1000,
5061
timeout: 3000,
5162
retries: 5,
5263
})
53-
.withWaitStrategy(Wait.forHealthCheck())
64+
.withWaitStrategy(
65+
Wait.forAll([Wait.forHealthCheck(), Wait.forLogMessage("Ready to accept connections")])
66+
)
5467
.start();
5568

69+
// Add a verification step
70+
await verifyRedisConnection(startedContainer);
71+
5672
return {
57-
container,
73+
container: startedContainer,
5874
};
5975
}
6076

77+
async function verifyRedisConnection(container: StartedRedisContainer) {
78+
const redis = new Redis({
79+
host: container.getHost(),
80+
port: container.getPort(),
81+
password: container.getPassword(),
82+
maxRetriesPerRequest: 3,
83+
connectTimeout: 10000,
84+
retryStrategy(times) {
85+
const delay = Math.min(times * 50, 2000);
86+
return delay;
87+
},
88+
});
89+
90+
try {
91+
await redis.ping();
92+
} finally {
93+
await redis.quit();
94+
}
95+
}
96+
6197
export async function createElectricContainer(
6298
postgresContainer: StartedPostgreSqlContainer,
6399
network: StartedNetwork

0 commit comments

Comments
 (0)