+sub x_sync {
+ my ($json,$old) = @_;
+ $json->{$_} = $old->{$_} foreach keys %{ $old->{x_meta} }; # special persistent x_meta fields
+ my $json_md5 = md5_hex encode_json $json;
+ $json->{x_sync}->{json_md5} = $json_md5;
+ my $o = $old->{x_sync}->{json_md5};
+ my $n = $json->{x_sync}->{json_md5};
+ warn "## x_sync $o ", $o eq $n ? '==' : '!=', " $n\n";
+ return $json;
+}
+
+
+sub modify {
+ my ($self, $url, $json) = @_;
+
+ carp "# modify $url ", ref $json;
+
+ my $ret;
+
+ if ( my $old = eval { $self->get( $url ) } ) {
+ warn "# old ", $old->{_rev}, dump($old);
+
+ if ( ref $json eq 'CODE' ) {
+ $json = $json->( clone $old );
+ warn "# json CODE ",dump($json);
+ } else {
+ warn "# overwrite old";
+ $json->{_rev} = $old->{_rev};
+ }
+
+ $json = x_sync($json, $old);
+
+ if ( $json->{x_sync}->{json_md5} ne $old->{x_sync}->{json_md5} ) {
+ warn "# modify $url";
+ $ret = $self->put( $url => $json );
+ } else {
+ warn "# unchanged $url";
+ $ret->{rev} = $old->{_rev};
+ $ret->{id} = $old->{_id};
+ }
+ } else {
+ $json = $json->({}) if ref $json eq 'CODE';
+
+ $json = x_sync($json);
+
+ warn "# insert $url ", dump($json);
+ $ret = $self->put( $url => $json );
+ }
+
+ return $ret;
+}
+