Skip to content

Commit e1d03ef

Browse files
authored
Add immutable 'operator' metadata classes for cluster state (#87763)
This commit only introduces the storage classes, unused for now. Relates to #86224
1 parent 244c248 commit e1d03ef

15 files changed

+1020
-68
lines changed

server/src/main/java/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@
275275
exports org.elasticsearch.monitor.os;
276276
exports org.elasticsearch.monitor.process;
277277
exports org.elasticsearch.node;
278-
exports org.elasticsearch.operator;
278+
exports org.elasticsearch.immutablestate;
279279
exports org.elasticsearch.persistent;
280280
exports org.elasticsearch.persistent.decider;
281281
exports org.elasticsearch.plugins;
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.cluster.metadata;
10+
11+
import org.elasticsearch.cluster.Diff;
12+
import org.elasticsearch.cluster.SimpleDiffable;
13+
import org.elasticsearch.common.io.stream.StreamInput;
14+
import org.elasticsearch.common.io.stream.StreamOutput;
15+
import org.elasticsearch.xcontent.ConstructingObjectParser;
16+
import org.elasticsearch.xcontent.ParseField;
17+
import org.elasticsearch.xcontent.ToXContentFragment;
18+
import org.elasticsearch.xcontent.XContentBuilder;
19+
import org.elasticsearch.xcontent.XContentParser;
20+
21+
import java.io.IOException;
22+
import java.util.List;
23+
24+
import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
25+
26+
/**
27+
* A metadata class to hold error information about errors encountered
28+
* while applying a cluster state update for a given namespace.
29+
* <p>
30+
* This information is held by the {@link ImmutableStateMetadata} class.
31+
*/
32+
public record ImmutableStateErrorMetadata(Long version, ErrorKind errorKind, List<String> errors)
33+
implements
34+
SimpleDiffable<ImmutableStateErrorMetadata>,
35+
ToXContentFragment {
36+
37+
static final ParseField ERRORS = new ParseField("errors");
38+
static final ParseField VERSION = new ParseField("version");
39+
static final ParseField ERROR_KIND = new ParseField("error_kind");
40+
41+
/**
42+
* Constructs an immutable state error metadata
43+
*
44+
* @param version the metadata version of the content which failed to apply
45+
* @param errorKind the kind of error we encountered while processing
46+
* @param errors the list of errors encountered during parsing and validation of the immutable state content
47+
*/
48+
public ImmutableStateErrorMetadata {}
49+
50+
@Override
51+
public void writeTo(StreamOutput out) throws IOException {
52+
out.writeLong(version);
53+
out.writeString(errorKind.getKindValue());
54+
out.writeCollection(errors, StreamOutput::writeString);
55+
}
56+
57+
/**
58+
* Reads an {@link ImmutableStateErrorMetadata} from a {@link StreamInput}
59+
*
60+
* @param in the {@link StreamInput} to read from
61+
* @return {@link ImmutableStateErrorMetadata}
62+
* @throws IOException
63+
*/
64+
public static ImmutableStateErrorMetadata readFrom(StreamInput in) throws IOException {
65+
return new ImmutableStateErrorMetadata(in.readLong(), ErrorKind.of(in.readString()), in.readList(StreamInput::readString));
66+
}
67+
68+
@Override
69+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
70+
builder.startObject();
71+
builder.field(VERSION.getPreferredName(), version);
72+
builder.field(ERROR_KIND.getPreferredName(), errorKind.getKindValue());
73+
builder.stringListField(ERRORS.getPreferredName(), errors);
74+
builder.endObject();
75+
return builder;
76+
}
77+
78+
@SuppressWarnings("unchecked")
79+
private static final ConstructingObjectParser<ImmutableStateErrorMetadata, Void> PARSER = new ConstructingObjectParser<>(
80+
"immutable_state_error_metadata",
81+
(a) -> new ImmutableStateErrorMetadata((Long) a[0], ErrorKind.of((String) a[1]), (List<String>) a[2])
82+
);
83+
84+
static {
85+
PARSER.declareLong(constructorArg(), VERSION);
86+
PARSER.declareString(constructorArg(), ERROR_KIND);
87+
PARSER.declareStringArray(constructorArg(), ERRORS);
88+
}
89+
90+
/**
91+
* Reads an {@link ImmutableStateErrorMetadata} from xContent
92+
*
93+
* @param parser {@link XContentParser}
94+
* @return {@link ImmutableStateErrorMetadata}
95+
*/
96+
public static ImmutableStateErrorMetadata fromXContent(final XContentParser parser) {
97+
return PARSER.apply(parser, null);
98+
}
99+
100+
/**
101+
* Reads an {@link ImmutableStateErrorMetadata} {@link Diff} from {@link StreamInput}
102+
*
103+
* @param in the {@link StreamInput} to read the diff from
104+
* @return a {@link Diff} of {@link ImmutableStateErrorMetadata}
105+
* @throws IOException
106+
*/
107+
public static Diff<ImmutableStateErrorMetadata> readDiffFrom(StreamInput in) throws IOException {
108+
return SimpleDiffable.readDiffFrom(ImmutableStateErrorMetadata::readFrom, in);
109+
}
110+
111+
/**
112+
* Enum for kinds of errors we might encounter while processing immutable cluster state updates.
113+
*/
114+
public enum ErrorKind {
115+
PARSING("parsing"),
116+
VALIDATION("validation"),
117+
TRANSIENT("transient");
118+
119+
private final String kind;
120+
121+
ErrorKind(String kind) {
122+
this.kind = kind;
123+
}
124+
125+
/**
126+
* Returns the String value for this enum value
127+
*
128+
* @return the String value for the enum
129+
*/
130+
public String getKindValue() {
131+
return kind;
132+
}
133+
134+
/**
135+
* Helper method to construct {@link ErrorKind} from a String.
136+
*
137+
* The JDK default implementation throws incomprehensible error.
138+
* @param kind String value
139+
* @return {@link ErrorKind}
140+
*/
141+
public static ErrorKind of(String kind) {
142+
for (var report : values()) {
143+
if (report.kind.equals(kind)) {
144+
return report;
145+
}
146+
}
147+
throw new IllegalArgumentException("kind not supported [" + kind + "]");
148+
}
149+
}
150+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.cluster.metadata;
10+
11+
import org.elasticsearch.cluster.Diff;
12+
import org.elasticsearch.cluster.SimpleDiffable;
13+
import org.elasticsearch.common.io.stream.StreamInput;
14+
import org.elasticsearch.common.io.stream.StreamOutput;
15+
import org.elasticsearch.immutablestate.ImmutableClusterStateHandler;
16+
import org.elasticsearch.xcontent.ConstructingObjectParser;
17+
import org.elasticsearch.xcontent.ParseField;
18+
import org.elasticsearch.xcontent.ToXContentFragment;
19+
import org.elasticsearch.xcontent.XContentBuilder;
20+
import org.elasticsearch.xcontent.XContentParser;
21+
22+
import java.io.IOException;
23+
import java.util.List;
24+
import java.util.Set;
25+
26+
import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
27+
28+
/**
29+
* Metadata class to hold a set of immutable keys in the cluster state, set by each {@link ImmutableClusterStateHandler}.
30+
*
31+
* <p>
32+
* Since we hold immutable metadata state for multiple namespaces, the same handler can appear in
33+
* multiple namespaces. See {@link ImmutableStateMetadata} and {@link Metadata}.
34+
*/
35+
public record ImmutableStateHandlerMetadata(String name, Set<String> keys)
36+
implements
37+
SimpleDiffable<ImmutableStateHandlerMetadata>,
38+
ToXContentFragment {
39+
40+
static final ParseField KEYS = new ParseField("keys");
41+
42+
@Override
43+
public void writeTo(StreamOutput out) throws IOException {
44+
out.writeString(name);
45+
out.writeCollection(keys, StreamOutput::writeString);
46+
}
47+
48+
/**
49+
* Reads an {@link ImmutableStateHandlerMetadata} from a {@link StreamInput}
50+
*
51+
* @param in the {@link StreamInput} to read from
52+
* @return {@link ImmutableStateHandlerMetadata}
53+
* @throws IOException
54+
*/
55+
public static ImmutableStateHandlerMetadata readFrom(StreamInput in) throws IOException {
56+
return new ImmutableStateHandlerMetadata(in.readString(), in.readSet(StreamInput::readString));
57+
}
58+
59+
@Override
60+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
61+
builder.startObject(name());
62+
builder.stringListField(KEYS.getPreferredName(), keys().stream().sorted().toList()); // ordered keys for output consistency
63+
builder.endObject();
64+
return builder;
65+
}
66+
67+
@SuppressWarnings("unchecked")
68+
private static final ConstructingObjectParser<ImmutableStateHandlerMetadata, String> PARSER = new ConstructingObjectParser<>(
69+
"immutable_state_handler_metadata",
70+
false,
71+
(a, name) -> new ImmutableStateHandlerMetadata(name, Set.copyOf((List<String>) a[0]))
72+
);
73+
74+
static {
75+
PARSER.declareStringArray(optionalConstructorArg(), KEYS);
76+
}
77+
78+
/**
79+
* Reads an {@link ImmutableStateHandlerMetadata} from xContent
80+
*
81+
* @param parser {@link XContentParser}
82+
* @return {@link ImmutableStateHandlerMetadata}
83+
* @throws IOException
84+
*/
85+
public static ImmutableStateHandlerMetadata fromXContent(XContentParser parser, String name) throws IOException {
86+
return PARSER.apply(parser, name);
87+
}
88+
89+
/**
90+
* Reads an {@link ImmutableStateHandlerMetadata} {@link Diff} from {@link StreamInput}
91+
*
92+
* @param in the {@link StreamInput} to read the diff from
93+
* @return a {@link Diff} of {@link ImmutableStateHandlerMetadata}
94+
* @throws IOException
95+
*/
96+
public static Diff<ImmutableStateHandlerMetadata> readDiffFrom(StreamInput in) throws IOException {
97+
return SimpleDiffable.readDiffFrom(ImmutableStateHandlerMetadata::readFrom, in);
98+
}
99+
}

0 commit comments

Comments
 (0)