or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cluster-client.mdcluster-singleton.mddistributed-pubsub.mdindex.md

cluster-singleton.mddocs/

0

# Cluster Singleton

1

2

The Cluster Singleton pattern ensures that exactly one instance of a particular actor is running somewhere in the cluster at any point in time. This is useful for central coordination, resource management, or any scenario where you need exactly-one semantics in a distributed system.

3

4

## Capabilities

5

6

### ClusterSingletonManager

7

8

Manages a singleton actor instance, ensuring it runs on exactly one node with automatic failover.

9

10

```scala { .api }

11

/**

12

* Manages singleton actor instance among all cluster nodes or a group

13

* of nodes tagged with a specific role. At most one singleton instance

14

* is running at any point in time.

15

*

16

* @param singletonProps Props of the singleton actor instance

17

* @param terminationMessage Message sent to singleton during hand-over

18

* @param settings Configuration settings

19

*/

20

class ClusterSingletonManager(

21

singletonProps: Props,

22

terminationMessage: Any,

23

settings: ClusterSingletonManagerSettings

24

) extends Actor

25

26

object ClusterSingletonManager {

27

/**

28

* Scala API: Factory method for ClusterSingletonManager Props

29

*/

30

def props(

31

singletonProps: Props,

32

terminationMessage: Any,

33

settings: ClusterSingletonManagerSettings

34

): Props

35

}

36

```

37

38

**Usage Example:**

39

40

```scala

41

import akka.actor.{ActorSystem, Props, PoisonPill}

42

import akka.cluster.singleton.{ClusterSingletonManager, ClusterSingletonManagerSettings}

43

44

implicit val system: ActorSystem = ActorSystem("cluster-system")

45

46

// Create singleton manager

47

val singletonManager = system.actorOf(

48

ClusterSingletonManager.props(

49

singletonProps = Props[DatabaseCoordinator](),

50

terminationMessage = PoisonPill,

51

settings = ClusterSingletonManagerSettings(system)

52

.withRole("backend")

53

.withSingletonName("db-coordinator")

54

),

55

name = "database-singleton"

56

)

57

```

58

59

### ClusterSingletonProxy

60

61

Provides a proxy to communicate with the singleton actor, handling location transparency and buffering.

62

63

```scala { .api }

64

/**

65

* Proxy that forwards messages to the singleton actor.

66

* Can be started on any node to provide location-transparent access.

67

* Buffers messages when singleton is unavailable during hand-over.

68

*

69

* @param singletonManagerPath Logical path to the singleton manager

70

* @param settings Configuration settings

71

*/

72

class ClusterSingletonProxy(

73

singletonManagerPath: String,

74

settings: ClusterSingletonProxySettings

75

) extends Actor

76

77

object ClusterSingletonProxy {

78

/**

79

* Scala API: Factory method for ClusterSingletonProxy Props

80

*

81

* @param singletonManagerPath The logical path of the singleton manager

82

* @param settings Configuration settings

83

*/

84

def props(

85

singletonManagerPath: String,

86

settings: ClusterSingletonProxySettings

87

): Props

88

}

89

```

90

91

**Usage Example:**

92

93

```scala

94

import akka.cluster.singleton.{ClusterSingletonProxy, ClusterSingletonProxySettings}

95

96

// Create proxy to communicate with singleton

97

val singletonProxy = system.actorOf(

98

ClusterSingletonProxy.props(

99

singletonManagerPath = "/user/database-singleton",

100

settings = ClusterSingletonProxySettings(system)

101

.withRole("backend")

102

.withSingletonName("db-coordinator")

103

.withBufferSize(1000)

104

),

105

name = "database-proxy"

106

)

107

108

// Send messages to singleton via proxy

109

singletonProxy ! "process-batch"

110

singletonProxy ! GetStatus

111

```

112

113

### ClusterSingletonManagerSettings

114

115

Configuration for the singleton manager behavior.

116

117

```scala { .api }

118

/**

119

* Configuration settings for ClusterSingletonManager

120

*

121

* @param singletonName The actor name of the child singleton actor

122

* @param role Singleton among nodes tagged with specified role. None means all nodes

123

* @param removalMargin Margin until singleton is created in surviving partition after split

124

* @param handOverRetryInterval Retry interval for hand-over requests

125

* @param leaseSettings Optional lease configuration for singleton coordination

126

*/

127

final class ClusterSingletonManagerSettings(

128

val singletonName: String,

129

val role: Option[String],

130

val removalMargin: FiniteDuration,

131

val handOverRetryInterval: FiniteDuration,

132

val leaseSettings: Option[LeaseUsageSettings]

133

) extends NoSerializationVerificationNeeded

134

135

object ClusterSingletonManagerSettings {

136

/**

137

* Create settings from the default configuration akka.cluster.singleton

138

*/

139

def apply(system: ActorSystem): ClusterSingletonManagerSettings

140

141

/**

142

* Create settings from a configuration with the same layout as

143

* the default configuration akka.cluster.singleton

144

*/

145

def apply(config: Config): ClusterSingletonManagerSettings

146

147

/**

148

* Java API: Create settings from the default configuration

149

*/

150

def create(system: ActorSystem): ClusterSingletonManagerSettings

151

152

/**

153

* Java API: Create settings from configuration

154

*/

155

def create(config: Config): ClusterSingletonManagerSettings

156

}

157

```

158

159

**Settings Methods:**

160

161

```scala { .api }

162

// Configuration methods for ClusterSingletonManagerSettings

163

def withSingletonName(name: String): ClusterSingletonManagerSettings

164

def withRole(role: String): ClusterSingletonManagerSettings

165

def withRole(role: Option[String]): ClusterSingletonManagerSettings

166

def withRemovalMargin(removalMargin: FiniteDuration): ClusterSingletonManagerSettings

167

def withHandOverRetryInterval(retryInterval: FiniteDuration): ClusterSingletonManagerSettings

168

def withLeaseSettings(leaseSettings: LeaseUsageSettings): ClusterSingletonManagerSettings

169

```

170

171

### ClusterSingletonProxySettings

172

173

Configuration for the singleton proxy behavior.

174

175

```scala { .api }

176

/**

177

* Configuration settings for ClusterSingletonProxy

178

*

179

* @param singletonName The actor name of the singleton actor started by ClusterSingletonManager

180

* @param role The role of cluster nodes where singleton can be deployed

181

* @param dataCenter The data center of cluster nodes where singleton is running

182

* @param singletonIdentificationInterval Interval at which proxy tries to resolve singleton

183

* @param bufferSize Number of messages to buffer when singleton location unknown

184

*/

185

final class ClusterSingletonProxySettings(

186

val singletonName: String,

187

val role: Option[String],

188

val dataCenter: Option[DataCenter],

189

val singletonIdentificationInterval: FiniteDuration,

190

val bufferSize: Int

191

) extends NoSerializationVerificationNeeded

192

193

object ClusterSingletonProxySettings {

194

/**

195

* Create settings from the default configuration akka.cluster.singleton-proxy

196

*/

197

def apply(system: ActorSystem): ClusterSingletonProxySettings

198

199

/**

200

* Create settings from configuration

201

*/

202

def apply(config: Config): ClusterSingletonProxySettings

203

204

/**

205

* Java API: Create settings from default configuration

206

*/

207

def create(system: ActorSystem): ClusterSingletonProxySettings

208

209

/**

210

* Java API: Create settings from configuration

211

*/

212

def create(config: Config): ClusterSingletonProxySettings

213

}

214

```

215

216

**Settings Methods:**

217

218

```scala { .api }

219

// Configuration methods for ClusterSingletonProxySettings

220

def withSingletonName(name: String): ClusterSingletonProxySettings

221

def withRole(role: String): ClusterSingletonProxySettings

222

def withRole(role: Option[String]): ClusterSingletonProxySettings

223

def withDataCenter(dataCenter: DataCenter): ClusterSingletonProxySettings

224

def withDataCenter(dataCenter: Option[DataCenter]): ClusterSingletonProxySettings

225

def withSingletonIdentificationInterval(interval: FiniteDuration): ClusterSingletonProxySettings

226

def withBufferSize(bufferSize: Int): ClusterSingletonProxySettings

227

```

228

229

### Exception Types

230

231

```scala { .api }

232

/**

233

* Thrown when a consistent state can't be determined within the defined retry limits.

234

* Parent supervisor should typically restart the actor.

235

*/

236

class ClusterSingletonManagerIsStuck(message: String) extends AkkaException

237

```

238

239

## Common Usage Patterns

240

241

### Database Coordinator Singleton

242

243

```scala

244

// Singleton that coordinates database operations

245

class DatabaseCoordinator extends Actor {

246

def receive = {

247

case "process-batch" =>

248

// Process batch operations

249

sender() ! "batch-processed"

250

case GetStatus =>

251

sender() ! DatabaseStatus("active", processedBatches = 42)

252

}

253

}

254

255

// Setup singleton manager and proxy

256

val manager = system.actorOf(

257

ClusterSingletonManager.props(

258

Props[DatabaseCoordinator](),

259

terminationMessage = "shutdown",

260

ClusterSingletonManagerSettings(system).withRole("backend")

261

),

262

"db-coordinator-singleton"

263

)

264

265

val proxy = system.actorOf(

266

ClusterSingletonProxy.props(

267

"/user/db-coordinator-singleton",

268

ClusterSingletonProxySettings(system).withRole("backend")

269

),

270

"db-coordinator-proxy"

271

)

272

```

273

274

### Leader Election Pattern

275

276

```scala

277

// Use singleton for leader election

278

class ClusterLeader extends Actor {

279

override def preStart(): Unit = {

280

super.preStart()

281

log.info("I am the leader!")

282

// Initialize leader-specific operations

283

}

284

285

def receive = {

286

case "election-status" => sender() ! "leader"

287

case LeaderTask(work) =>

288

// Only the leader processes these tasks

289

processLeaderWork(work)

290

}

291

}

292

```

293

294

## Types

295

296

```scala { .api }

297

// Required imports for singleton functionality

298

import akka.actor.{Actor, ActorRef, ActorSystem, Props}

299

import akka.cluster.ClusterSettings.DataCenter

300

import akka.coordination.lease.LeaseUsageSettings

301

import com.typesafe.config.Config

302

import scala.concurrent.duration.FiniteDuration

303

```