22
33import java .io .File ;
44import java .time .Instant ;
5+ import java .util .Collections ;
56import java .util .Map ;
67import java .util .TreeMap ;
78
1617import gov .nasa .pds .registry .common .dd .parser .DDAttribute ;
1718import gov .nasa .pds .registry .common .es .dao .DataLoader ;
1819import gov .nasa .pds .registry .common .es .dao .dd .DataDictionaryDao ;
20+ import gov .nasa .pds .registry .common .es .dao .dd .DataTypeNotFoundException ;
1921import gov .nasa .pds .registry .common .es .dao .dd .LddVersions ;
2022
2123
@@ -88,6 +90,10 @@ public void load(File lddFile, String lddFileName, String namespace) throws Exce
8890 namespace = LddUtils .getLddNamespace (lddFile );
8991 }
9092
93+ // get date of the current LDD for this namespace in the registry. If there is no LDD for this namespace, use epoch date.
94+ // TODO add the test of overwrite yes/no, remove it from where it is not >?
95+
96+
9197 // Get information about LDDs already loaded into the registry (for this namespace)
9298 LddVersions info = dao .getLddInfo (namespace );
9399 if (info .files .contains (lddFileName )) {
@@ -118,8 +124,42 @@ public void loadOnly(File lddFile, String lddFileName, String namespace, Instant
118124 log .info ("Creating temporary ES data file " + tempEsDataFile .getAbsolutePath ());
119125
120126 try {
121- createEsDataFile (lddFile , lddFileName , namespace , tempEsDataFile , lastDate );
127+ String firstFieldId = createEsDataFile (lddFile , lddFileName , namespace , tempEsDataFile , lastDate );
122128 loader .loadFile (tempEsDataFile );
129+
130+ // Wait until the LDD_Info sentinel is visible (search with requestCache=false).
131+ // This confirms the bulk load completed on the server side.
132+ LddVersions info = dao .getLddInfoNoCache (namespace );
133+ int nAttempts = 0 ;
134+ int maxAttempts = 30 ;
135+ while (info .isEmpty () && nAttempts < maxAttempts ) {
136+ Thread .sleep (1000 );
137+ log .info ("Waiting for the new LDD {} to be indexed..." , namespace );
138+ info = dao .getLddInfoNoCache (namespace );
139+ }
140+
141+ if (info .isEmpty ()) {
142+ log .warn ("The new LDD {} is not indexed after {} seconds. It may be indexed later, but there may be a delay in loading other LDDs for this namespace." , namespace , maxAttempts );
143+ } else {
144+ log .info ("The new LDD {} is indexed with date {}. It may take some time for it to be visible via mget." , namespace , info .lastDate );
145+
146+ // On AWS OpenSearch Serverless (AOSS), mget and search use different visibility paths.
147+ // Wait until a specific field document is also visible via mget with refresh=true,
148+ // so that getDataTypes() calls immediately following this load will succeed.
149+ if (firstFieldId != null ) {
150+ boolean fieldVisible = false ;
151+ while (!fieldVisible ) {
152+ try {
153+ dao .getDataTypesWithRefresh (Collections .singletonList (firstFieldId ));
154+ fieldVisible = true ;
155+ } catch (DataTypeNotFoundException e ) {
156+ Thread .sleep (1000 );
157+ log .info ("Waiting for field {} of namespace {} to be visible via mget..." , firstFieldId , namespace );
158+ }
159+ }
160+ }
161+ log .info ("Visibility of namespace " + namespace + "has been fully validated." );
162+ }
123163 } finally {
124164 // Delete temporary file
125165 tempEsDataFile .delete ();
@@ -128,15 +168,30 @@ public void loadOnly(File lddFile, String lddFileName, String namespace, Instant
128168
129169
130170 private static class CaaCallback implements ClassAttrAssociationParser .Callback {
131- private LddEsJsonWriter writer ;
171+ private final LddEsJsonWriter writer ;
172+ private final String namespace ;
173+ private final Map <String , DDAttribute > ddAttrCache ;
174+ private String firstFieldId ;
132175
133- public CaaCallback (LddEsJsonWriter writer ) {
176+ public CaaCallback (LddEsJsonWriter writer , String namespace , Map < String , DDAttribute > ddAttrCache ) {
134177 this .writer = writer ;
178+ this .namespace = namespace ;
179+ this .ddAttrCache = ddAttrCache ;
135180 }
136181
137182 @ Override
138183 public void onAssociation (String classNs , String className , String attrId ) throws Exception {
139184 writer .writeFieldDefinition (classNs , className , attrId );
185+ if (firstFieldId == null && namespace .equals (classNs )) {
186+ DDAttribute attr = ddAttrCache .get (attrId );
187+ if (attr != null ) {
188+ firstFieldId = classNs + ":" + className + "/" + attr .attrNs + ":" + attr .attrName ;
189+ }
190+ }
191+ }
192+
193+ public String getFirstFieldId () {
194+ return firstFieldId ;
140195 }
141196 }
142197
@@ -149,7 +204,7 @@ public void onAssociation(String classNs, String className, String attrId) throw
149204 * @param tempEsFile Write to this Elasticsearch file
150205 * @throws Exception an exception
151206 */
152- private void createEsDataFile (File lddFile , String lddFileName , String namespace , File tempEsFile ,
207+ private String createEsDataFile (File lddFile , String lddFileName , String namespace , File tempEsFile ,
153208 Instant lastDate ) throws Exception {
154209 // Parse and cache LDD attributes
155210 Map <String , DDAttribute > ddAttrCache = new TreeMap <>();
@@ -169,13 +224,15 @@ private void createEsDataFile(File lddFile, String lddFileName, String namespace
169224 writer .setNamespaceFilter (namespace );
170225
171226 // Parse class attribute associations and write to ES data file
172- CaaCallback ccb = new CaaCallback (writer );
227+ CaaCallback ccb = new CaaCallback (writer , namespace , ddAttrCache );
173228 ClassAttrAssociationParser caaParser = new ClassAttrAssociationParser (lddFile , ccb );
174229 caaParser .parse ();
175230
176231 // Write data dictionary version and date
177232 writer .writeLddInfo (namespace , lddFileName , attrParser .getImVersion (),
178233 attrParser .getLddVersion (), attrParser .getLddDate ());
234+
235+ return ccb .getFirstFieldId ();
179236 } finally {
180237 writer .close ();
181238 }
0 commit comments